Mercurial > pub > bltoolkit
view Source/TypeBuilder/Builders/GeneratedAttributeBuilder.cs @ 9:1e85f66cf767 default tip
update bltoolkit
author | nickolay |
---|---|
date | Thu, 05 Apr 2018 20:53:26 +0300 |
parents | f990fcb411a9 |
children |
line wrap: on
line source
using System; using System.Collections.Generic; using System.Reflection; using System.Reflection.Emit; using BLToolkit.Reflection; namespace BLToolkit.TypeBuilder.Builders { internal class GeneratedAttributeBuilder : AbstractTypeBuilderBase { private CustomAttributeBuilder _attributeBuilder; public GeneratedAttributeBuilder(Type attributeType, object[] arguments, string[] names, object[] values) { if (attributeType == null) throw new ArgumentNullException("attributeType"); ConstructorInfo constructor = null; if (arguments == null || arguments.Length == 0) { constructor = attributeType.GetConstructor(Type.EmptyTypes); arguments = Type.EmptyTypes; } else { // Some arguments may be null. We can not infer a type from the null reference. // So we must iterate all of them and got a suitable one. // foreach (ConstructorInfo ci in attributeType.GetConstructors()) { if (CheckParameters(ci.GetParameters(), arguments)) { constructor = ci; break; } } } if (constructor == null) throw new TypeBuilderException(string.Format("No suitable constructors found for the type '{0}'.", attributeType.FullName)); if (names == null || names.Length == 0) { _attributeBuilder = new CustomAttributeBuilder(constructor, arguments); } else if (values == null || names.Length != values.Length) { throw new TypeBuilderException(string.Format("Named argument names count should match named argument values count.")); } else { List<PropertyInfo> namedProperties = new List<PropertyInfo>(); List<object> propertyValues = new List<object>(); List<FieldInfo> namedFields = new List<FieldInfo>(); List<object> fieldValues = new List<object>(); for (int i = 0; i < names.Length; i++) { string name = names[i]; MemberInfo[] mi = attributeType.GetMember(name); if (mi.Length == 0) throw new TypeBuilderException(string.Format("The type '{0}' does not have a public member '{1}'.", attributeType.FullName, name)); if (mi[0].MemberType == MemberTypes.Property) { namedProperties.Add((PropertyInfo)mi[0]); propertyValues.Add(values[i]); } else if (mi[0].MemberType == MemberTypes.Field) { namedFields.Add((FieldInfo)mi[0]); fieldValues.Add(values[i]); } else throw new TypeBuilderException(string.Format("The member '{1}' of the type '{0}' is not a filed nor a property.", name, attributeType.FullName)); } _attributeBuilder = new CustomAttributeBuilder(constructor, arguments, namedProperties.ToArray(), propertyValues.ToArray(), namedFields.ToArray(), fieldValues.ToArray()); } } private static bool CheckParameters(ParameterInfo[] argumentTypes, object[] arguments) { if (argumentTypes.Length != arguments.Length) return false; for (int i = 0; i < arguments.Length; i++) { if (arguments[i] == null && argumentTypes[i].ParameterType.IsClass) continue; if (argumentTypes[i].ParameterType.IsAssignableFrom(arguments[i].GetType())) continue; // Bad match // return false; } return true; } public override bool IsApplied(BuildContext context, AbstractTypeBuilderList builders) { return context.IsAfterStep && context.BuildElement == BuildElement.Type == TargetElement is TypeHelper; } public override void Build(BuildContext context) { if (context.BuildElement == BuildElement.Type) { context.TypeBuilder.TypeBuilder.SetCustomAttribute(_attributeBuilder); } else if (TargetElement is MethodInfo) { context.MethodBuilder.MethodBuilder.SetCustomAttribute(_attributeBuilder); } else if (TargetElement is PropertyInfo && context.IsAbstractProperty) { if (_attributeBuilder != null) { var field = context.Fields[(PropertyInfo)TargetElement]; field.SetCustomAttribute(_attributeBuilder); // Suppress multiple instances when the property has both getter and setter. // _attributeBuilder = null; } } } } }