/// <summary> Calculate if an enabled if is enabled by a given value. </summary> static bool calcEnabled2(EnabledIfAttribute at, object depValue) { if (at.Flags) { int value = (int)Convert.ChangeType(depValue, TypeCode.Int32); foreach (var flag in at.PropertyValues) { int flagCode = (int)Convert.ChangeType(flag, TypeCode.Int32); if ((value & flagCode) != 0) { return(true); } } return(false); } if (depValue is IEnabled e) { depValue = e.IsEnabled; } foreach (var val in at.PropertyValues) { if (object.Equals(val, depValue)) { return(true); } } return(false); }
/// <summary> /// Checks whether a given property is enabled according to the <see cref="EnabledIfAttribute"/>. /// </summary> /// <param name="at">The attribute enabling this property.</param> /// <param name="instance">Instance of the object that has 'property'.</param> /// <returns>true if property dependent property has the correct value.</returns> internal static bool IsEnabled(EnabledIfAttribute at, object instance) { IMemberData depedentProp = TypeData.GetTypeData(instance).GetMember(at.PropertyName); if (depedentProp == null) { // We cannot be sure that the step developer has used this attribute correctly // (could just be a typo in the (weakly typed) property name), thus we need to // provide a good error message that leads the developer to where the error is. log.Warning("Could not find property '{0}' on '{1}'. EnabledIfAttribute can only refer to properties of the same class as the property it is decorating.", at.PropertyName, instance.GetType().Name); return(false); } var depValue = depedentProp.GetValue(instance); try { return(calcEnabled(at, depValue)); } catch (ArgumentException) { // CompareTo throws ArgumentException when obj is not the same type as this instance. return(false); } }
static bool calcEnabled(EnabledIfAttribute at, object value) { if (at.Invert) { return(!calcEnabled2(at, value)); } return(calcEnabled2(at, value)); }
/// <summary> /// Loads and transform the list of attributes. /// Some attributes are sensitive to naming, the known ones are AvailableValuesAttribute, /// SuggestedValueAttribute, and EnabledIf. Others might exist, but they are, for now, not supported. /// When NoPrefix is set on EmbedProperties, then there is no issue, but with the prefix, those names also needs /// to be transformed. /// Additionally, there is some special behavior wanted for Display, for usability and to avoid name clashing: /// - If a Display name/group is set on the owner property, that should turn into a group for the embedded properties. /// - If there is no display name, use the prefix name for the group. /// - If there is no prefix name, don't touch DisplayAttribute. /// </summary> object[] loadAndTransformAttributes() { string prefix_name = null; var list = innerMember.Attributes.ToList(); var embed = ownerMember.GetAttribute <EmbedPropertiesAttribute>(); if (embed.PrefixPropertyName) { prefix_name = embed.Prefix ?? ownerMember.Name; } string[] pre_group1; string pre_name; double ownerOrder = -10000; bool collapsed = false; { var owner_display = ownerMember.GetAttribute <DisplayAttribute>(); if (owner_display == null) { owner_display = new DisplayAttribute(embed.PrefixPropertyName ? ownerMember.Name : ""); pre_group1 = owner_display.Group; pre_name = owner_display.Name; } else { collapsed = owner_display.Collapsed; ownerOrder = owner_display.Order; pre_group1 = owner_display.Group; pre_name = owner_display.Name; } } string name; string[] post_group; var d = list.OfType <DisplayAttribute>().FirstOrDefault(); if (d != null) { list.Remove(d); // need to re-add a new DisplayAttribute. name = d.Name; post_group = d.Group; if (d.Collapsed) { collapsed = true; } } else { name = Name; post_group = Array.Empty <string>(); } var groups = pre_group1.Concat(pre_name == null ? Array.Empty <string>() : new[] { pre_name }).Concat(post_group) .ToArray(); double order = -10000; { // calculate order: // if owner order is set, add it to the display order. if (d != null && d.Order != -10000.0) { order = d.Order; if (ownerOrder != -10000.0) { // if an order is specified, add the two orders together. // this makes sure that property groups can be arranged. order += ownerOrder; } } else { order = ownerOrder; } } d = new DisplayAttribute(name, Groups: groups, Description: d?.Description, Order: order, Collapsed: collapsed); list.Add(d); if (prefix_name != null) { // Transform properties that has issues with embedding. for (var i = 0; i < list.Count; i++) { var item = list[i]; if (item is AvailableValuesAttribute avail) { list[i] = new AvailableValuesAttribute(prefix_name + "." + avail.PropertyName); } else if (item is SuggestedValuesAttribute sug) { list[i] = new SuggestedValuesAttribute(prefix_name + "." + sug.PropertyName); } else if (item is EnabledIfAttribute enabled) { list[i] = new EnabledIfAttribute(prefix_name + "." + enabled.PropertyName, enabled.PropertyValues) { HideIfDisabled = enabled.HideIfDisabled }; } } } return(attributes = list.ToArray()); }