public override AttributeDeclaration GetAttributeDeclaration(Attribute attribute) { CustomValidationAttribute cva = (CustomValidationAttribute)attribute; // Our convention is that parameter validation in the CVA occurs when it is // first used. Simply ask the attribute to produce an error message, as this // will trigger an InvalidOperationException if the attribute is ill-formed cva.FormatErrorMessage(string.Empty); // Delegate to the base implementation to generate the attribute. // Note that the base implementation already checks that Types are // shared so we do not perform that check here. AttributeDeclaration attributeDeclaration = base.GetAttributeDeclaration(attribute); attributeDeclaration.RequiredTypes.Add(cva.ValidatorType); attributeDeclaration.RequiredMethods.Add(cva.ValidatorType.GetMethod(cva.Method)); return(attributeDeclaration); }
public override AttributeDeclaration GetAttributeDeclaration(Attribute attribute) { RangeAttribute rangeAttribute = (RangeAttribute)attribute; AttributeDeclaration attributeDeclaration = new AttributeDeclaration(typeof(RangeAttribute)); // Register required resources for this ValidationAttribute RegisterSharedResources(rangeAttribute, attributeDeclaration); bool declareOperandType = rangeAttribute.Minimum == null || rangeAttribute.Minimum.GetType() == typeof(string); // OperandType if (declareOperandType) { attributeDeclaration.ConstructorArguments.Add(rangeAttribute.OperandType); } // Minimum attributeDeclaration.ConstructorArguments.Add(rangeAttribute.Minimum); // Maximum attributeDeclaration.ConstructorArguments.Add(rangeAttribute.Maximum); // ErrorMessage if (rangeAttribute.ErrorMessage != null) { attributeDeclaration.NamedParameters.Add("ErrorMessage", rangeAttribute.ErrorMessage); } // ErrorMessageResourceType if (rangeAttribute.ErrorMessageResourceType != null) { attributeDeclaration.NamedParameters.Add("ErrorMessageResourceType", rangeAttribute.ErrorMessageResourceType); } // ErrorMessageResourceName if (rangeAttribute.ErrorMessageResourceName != null) { attributeDeclaration.NamedParameters.Add("ErrorMessageResourceName", rangeAttribute.ErrorMessageResourceName); } return(attributeDeclaration); }
/// <summary> /// Generates a <see cref="AttributeDeclaration"/> representation of an /// <see cref="EditableAttribute"/> instance. /// </summary> /// <param name="attribute">The <see cref="EditableAttribute"/>.</param> /// <returns>A <see cref="AttributeDeclaration"/> representation of /// <paramref name="attribute"/>.</returns> /// <exception cref="InvalidCastException">if <paramref name="attribute"/> is /// not a <see cref="EditableAttribute"/>.</exception> public override AttributeDeclaration GetAttributeDeclaration(Attribute attribute) { EditableAttribute editableAttribute = (EditableAttribute)attribute; AttributeDeclaration attributeDeclaration = new AttributeDeclaration(typeof(EditableAttribute)); bool allowEdit = editableAttribute.AllowEdit; bool allowInitialValue = editableAttribute.AllowInitialValue; // [EditableAttribute( {true|false} )] attributeDeclaration.ConstructorArguments.Add(allowEdit); // Only add the 'AllowInitialValue' parameter if its value does not match with // the 'AllowEdit' value. See the documentation of EditableAttribute for more info. if (allowEdit != allowInitialValue) { // [EditableAttribute( {true|false}, AllowInitialValue = {true|false} )] attributeDeclaration.NamedParameters.Add("AllowInitialValue", allowInitialValue); } return(attributeDeclaration); }
public override AttributeDeclaration GetAttributeDeclaration(Attribute attribute) { var uiHintAttribute = (UIHintAttribute)attribute; // We override this build method only to deal with the control parameters // which cannot be generated by the standard builder. If there are no // control parameters, let the standard builder do the work. IDictionary <string, object> controlParams = null; try { controlParams = uiHintAttribute.ControlParameters; } catch (InvalidOperationException e) { throw new AttributeBuilderException(e, typeof(UIHintAttribute), "ControlParameters"); } if (controlParams == null || controlParams.Count == 0) { return(base.GetAttributeDeclaration(attribute)); } var attributeDeclaration = new AttributeDeclaration(typeof(UIHintAttribute)); // UIHint[("uiHint", "presentationLayer")] attributeDeclaration.ConstructorArguments.Add(uiHintAttribute.UIHint); attributeDeclaration.ConstructorArguments.Add(uiHintAttribute.PresentationLayer); // UIHint[("uiHint", "presentationLayer", ...)] -- fill in all the optional params from control parameters foreach (var item in controlParams) { attributeDeclaration.ConstructorArguments.Add(item.Key); attributeDeclaration.ConstructorArguments.Add(item.Value); } return(attributeDeclaration); }
/// <summary> /// Returns a representative <see cref="AttributeDeclaration"/> for a given <see cref="Attribute"/> instance. /// </summary> /// <param name="attribute">An attribute instance to create a <see cref="AttributeDeclaration"/> for.</param> /// <returns>A <see cref="AttributeDeclaration"/> representing the <paramref name="attribute"/>.</returns> public virtual AttributeDeclaration GetAttributeDeclaration(Attribute attribute) { if (attribute == null) { throw new ArgumentNullException("attribute"); } Type attributeType = attribute.GetType(); AttributeDeclaration attributeDeclaration = new AttributeDeclaration(attributeType); // Strategy is as follows: // - Fetch all the public property values from the current attribute // - Determine the default value for all of these properties // - From these 2 lists, determine the set of "non-default" properties. These are what we must code gen. // - From this list, determine which of these can be set only through a ctor // - From the list of ctor properties and values, find the best ctor pattern for it and code gen that // - For all remaining non-default properties, code gen named argument setters List <PropertyMap> propertyMaps = this.BuildPropertyMaps(attribute); Dictionary <string, object> currentValues = GetPropertyValues(propertyMaps, attribute); Dictionary <string, object> defaultValues = GetDefaultPropertyValues(propertyMaps, attribute, currentValues); List <PropertyMap> nonDefaultProperties = GetNonDefaultProperties(propertyMaps, currentValues, defaultValues); List <PropertyMap> unsettableProperties = GetUnsettableProperties(nonDefaultProperties); // "Unsettable" properties are all those that can be set only through a ctor (they have no public setter). // Go find the best ctor pattern for them and code gen that much ParameterInfo[] ctorParameters = FindBestConstructor(unsettableProperties, currentValues, attributeType); if (ctorParameters == null) { // Return null, indicating we cannot build this attribute. return(null); } // We found a ctor that will accept all our properties that need to be set. // Generate ctor arguments to match this signature. // Note: the ctor pattern obviously may require other arguments that are also settable, // so if we pass a value to the ctor, we omit it from the set of named parameters below foreach (ParameterInfo parameter in ctorParameters) { PropertyMap matchedPropertyMap = null; foreach (PropertyMap map in propertyMaps) { PropertyInfo propertyInfo = map.Setter; if (propertyInfo.Name.Equals(parameter.Name, StringComparison.OrdinalIgnoreCase) && CanValueBeAssignedToType(parameter.ParameterType, currentValues[propertyInfo.Name])) { matchedPropertyMap = map; break; } } object value = matchedPropertyMap != null ? currentValues[matchedPropertyMap.Getter.Name] : DefaultInstanceForType(parameter.ParameterType); attributeDeclaration.ConstructorArguments.Add(value); // Remove this from our list of properties we need to set so the code below skips it if (matchedPropertyMap != null) { nonDefaultProperties.Remove(matchedPropertyMap); } } // For all remaining non-default properties, generate a named argument setter. // We sort these so the named parameters appear in a predictable order in generated code -- primarily for unit testing nonDefaultProperties.Sort(new Comparison <PropertyMap>((x, y) => string.Compare(x.Setter.Name, y.Setter.Name, StringComparison.Ordinal))); foreach (PropertyMap map in nonDefaultProperties) { attributeDeclaration.NamedParameters.Add(map.Setter.Name, currentValues[map.Getter.Name]); } return(attributeDeclaration); }
public override AttributeDeclaration GetAttributeDeclaration(Attribute attribute) { DisplayAttribute displayAttribute = (DisplayAttribute)attribute; AttributeDeclaration attributeDeclaration = new AttributeDeclaration(typeof(DisplayAttribute)); // By convention, the attribute parameters are not validated until an attempt is made to // access the resources. We do the following probe merely to trigger this validation process. // An InvalidOperationException will be thrown if the attribute is ill-formed. Type attributeType = attribute.GetType(); try { displayAttribute.GetName(); } catch (InvalidOperationException ex) { throw new AttributeBuilderException(ex, attributeType, "Name"); } try { displayAttribute.GetShortName(); } catch (InvalidOperationException ex) { throw new AttributeBuilderException(ex, attributeType, "ShortName"); } try { displayAttribute.GetDescription(); } catch (InvalidOperationException ex) { throw new AttributeBuilderException(ex, attributeType, "Description"); } try { displayAttribute.GetPrompt(); } catch (InvalidOperationException ex) { throw new AttributeBuilderException(ex, attributeType, "Prompt"); } // Add AutoGenerateField if (displayAttribute.GetAutoGenerateField().HasValue) { attributeDeclaration.NamedParameters.Add("AutoGenerateField", displayAttribute.AutoGenerateField); } // Add AutoGenerateFilter if (displayAttribute.GetAutoGenerateFilter().HasValue) { attributeDeclaration.NamedParameters.Add("AutoGenerateFilter", displayAttribute.AutoGenerateFilter); } // Add Description if (!string.IsNullOrEmpty(displayAttribute.Description)) { attributeDeclaration.NamedParameters.Add("Description", displayAttribute.Description); } // Add GroupName if (!string.IsNullOrEmpty(displayAttribute.GroupName)) { attributeDeclaration.NamedParameters.Add("GroupName", displayAttribute.GroupName); } // Add Name if (!string.IsNullOrEmpty(displayAttribute.Name)) { attributeDeclaration.NamedParameters.Add("Name", displayAttribute.Name); } // Add Order if (displayAttribute.GetOrder().HasValue) { attributeDeclaration.NamedParameters.Add("Order", displayAttribute.Order); } // Add Prompt if (!string.IsNullOrEmpty(displayAttribute.Prompt)) { attributeDeclaration.NamedParameters.Add("Prompt", displayAttribute.Prompt); } // Add ResourceType if (displayAttribute.ResourceType != null) { attributeDeclaration.NamedParameters.Add("ResourceType", displayAttribute.ResourceType); } // Add ShortName if (!string.IsNullOrEmpty(displayAttribute.ShortName)) { attributeDeclaration.NamedParameters.Add("ShortName", displayAttribute.ShortName); } return(attributeDeclaration); }