/// <summary> /// Adds a live input to the zone program. A live input is an input that can be controlled while /// the program is running and the program will respond to it in the way it's designed to. /// </summary> /// <param name="name">Name of the input.</param> /// <param name="action">The action that should occur when the input is set to a certain value. This will be defined by the /// subclasses of this class to perform certain actions when the this input is set to a certain value.</param> /// <returns>The input that was just added.</returns> protected ZoneProgramInput AddInput <T>(string name, Action <dynamic> action) { var input = new ZoneProgramInput(name, typeof(T)); Inputs.Add(input); input.Subscribe(action); return(input); }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var result = new ZoneProgramInput(); // Deserialize into a temporary JObject JObject obj = serializer.Deserialize <JObject>(reader); // Populate the ZoneProgramInput object with the contents serializer.Populate(obj.CreateReader(), result); // Overwrite the "Value" property with the correct value based on the // "Type" property. result.SetValue(obj.GetValue("value", StringComparison.OrdinalIgnoreCase) .ToObject(result.Type, serializer)); return(result); }
/// <summary> /// Adds a live input as a direct map to a member of the subclass. This essentially extends a property in /// the subclass as an input, which can be set to any value by the user. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="instance"></param> /// <param name="propertyName"></param> /// <param name="filterPredicate">The incoming value will be run through this filter predicate function and only set the value if the function returns true.</param> /// <returns></returns> protected ZoneProgramInput AddMappedInput <T>(object instance, string propertyName, Func <T, bool> filterPredicate = null) { var propertyInfo = instance.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var input = new ZoneProgramInput(propertyInfo.Name, propertyInfo.PropertyType); Inputs.Add(input); if (filterPredicate != null) { input.Subscribe(incomingValue => { if (filterPredicate(ConvertIncomingValue <T>(incomingValue))) { propertyInfo.SetValue(instance, incomingValue); } else { throw new WarningException("Incoming value out of range of valid input values."); } }); } else { input.Subscribe(incomingValue => { if (propertyInfo.CanWrite) { propertyInfo.SetValue(instance, ConvertIncomingValue <T>(incomingValue)); } else { throw new InvalidOperationException( $"Input {input.Name} has an underlying property without an accessible setter. Cannot set value for this property."); } }); } //set value of input to the value of the property input.SetValue(propertyInfo.GetValue(instance)); return(input); }