Mercurial > pub > bltoolkit
comparison Source/TypeBuilder/Builders/GeneratedAttributeBuilder.cs @ 0:f990fcb411a9
Копия текущей версии из github
| author | cin |
|---|---|
| date | Thu, 27 Mar 2014 21:46:09 +0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:f990fcb411a9 |
|---|---|
| 1 using System; | |
| 2 using System.Collections.Generic; | |
| 3 using System.Reflection; | |
| 4 using System.Reflection.Emit; | |
| 5 using BLToolkit.Reflection; | |
| 6 | |
| 7 namespace BLToolkit.TypeBuilder.Builders | |
| 8 { | |
| 9 internal class GeneratedAttributeBuilder : AbstractTypeBuilderBase | |
| 10 { | |
| 11 private CustomAttributeBuilder _attributeBuilder; | |
| 12 | |
| 13 public GeneratedAttributeBuilder(Type attributeType, object[] arguments, string[] names, object[] values) | |
| 14 { | |
| 15 if (attributeType == null) | |
| 16 throw new ArgumentNullException("attributeType"); | |
| 17 | |
| 18 ConstructorInfo constructor = null; | |
| 19 | |
| 20 if (arguments == null || arguments.Length == 0) | |
| 21 { | |
| 22 constructor = attributeType.GetConstructor(Type.EmptyTypes); | |
| 23 arguments = Type.EmptyTypes; | |
| 24 } | |
| 25 else | |
| 26 { | |
| 27 // Some arguments may be null. We can not infer a type from the null reference. | |
| 28 // So we must iterate all of them and got a suitable one. | |
| 29 // | |
| 30 foreach (ConstructorInfo ci in attributeType.GetConstructors()) | |
| 31 { | |
| 32 if (CheckParameters(ci.GetParameters(), arguments)) | |
| 33 { | |
| 34 constructor = ci; | |
| 35 break; | |
| 36 } | |
| 37 } | |
| 38 } | |
| 39 | |
| 40 if (constructor == null) | |
| 41 throw new TypeBuilderException(string.Format("No suitable constructors found for the type '{0}'.", attributeType.FullName)); | |
| 42 | |
| 43 if (names == null || names.Length == 0) | |
| 44 { | |
| 45 _attributeBuilder = new CustomAttributeBuilder(constructor, arguments); | |
| 46 } | |
| 47 else if (values == null || names.Length != values.Length) | |
| 48 { | |
| 49 throw new TypeBuilderException(string.Format("Named argument names count should match named argument values count.")); | |
| 50 } | |
| 51 else | |
| 52 { | |
| 53 List<PropertyInfo> namedProperties = new List<PropertyInfo>(); | |
| 54 List<object> propertyValues = new List<object>(); | |
| 55 List<FieldInfo> namedFields = new List<FieldInfo>(); | |
| 56 List<object> fieldValues = new List<object>(); | |
| 57 | |
| 58 for (int i = 0; i < names.Length; i++) | |
| 59 { | |
| 60 string name = names[i]; | |
| 61 MemberInfo[] mi = attributeType.GetMember(name); | |
| 62 | |
| 63 if (mi.Length == 0) | |
| 64 throw new TypeBuilderException(string.Format("The type '{0}' does not have a public member '{1}'.", attributeType.FullName, name)); | |
| 65 | |
| 66 if (mi[0].MemberType == MemberTypes.Property) | |
| 67 { | |
| 68 namedProperties.Add((PropertyInfo)mi[0]); | |
| 69 propertyValues.Add(values[i]); | |
| 70 } | |
| 71 else if (mi[0].MemberType == MemberTypes.Field) | |
| 72 { | |
| 73 namedFields.Add((FieldInfo)mi[0]); | |
| 74 fieldValues.Add(values[i]); | |
| 75 } | |
| 76 else | |
| 77 throw new TypeBuilderException(string.Format("The member '{1}' of the type '{0}' is not a filed nor a property.", name, attributeType.FullName)); | |
| 78 } | |
| 79 | |
| 80 _attributeBuilder = new CustomAttributeBuilder(constructor, arguments, | |
| 81 namedProperties.ToArray(), propertyValues.ToArray(), namedFields.ToArray(), fieldValues.ToArray()); | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 private static bool CheckParameters(ParameterInfo[] argumentTypes, object[] arguments) | |
| 86 { | |
| 87 if (argumentTypes.Length != arguments.Length) | |
| 88 return false; | |
| 89 | |
| 90 for (int i = 0; i < arguments.Length; i++) | |
| 91 { | |
| 92 if (arguments[i] == null && argumentTypes[i].ParameterType.IsClass) | |
| 93 continue; | |
| 94 | |
| 95 if (argumentTypes[i].ParameterType.IsAssignableFrom(arguments[i].GetType())) | |
| 96 continue; | |
| 97 | |
| 98 // Bad match | |
| 99 // | |
| 100 return false; | |
| 101 } | |
| 102 | |
| 103 return true; | |
| 104 } | |
| 105 | |
| 106 public override bool IsApplied(BuildContext context, AbstractTypeBuilderList builders) | |
| 107 { | |
| 108 return context.IsAfterStep && context.BuildElement == BuildElement.Type == TargetElement is TypeHelper; | |
| 109 } | |
| 110 | |
| 111 public override void Build(BuildContext context) | |
| 112 { | |
| 113 if (context.BuildElement == BuildElement.Type) | |
| 114 { | |
| 115 context.TypeBuilder.TypeBuilder.SetCustomAttribute(_attributeBuilder); | |
| 116 } | |
| 117 else if (TargetElement is MethodInfo) | |
| 118 { | |
| 119 context.MethodBuilder.MethodBuilder.SetCustomAttribute(_attributeBuilder); | |
| 120 } | |
| 121 else if (TargetElement is PropertyInfo && context.IsAbstractProperty) | |
| 122 { | |
| 123 if (_attributeBuilder != null) | |
| 124 { | |
| 125 var field = context.Fields[(PropertyInfo)TargetElement]; | |
| 126 | |
| 127 field.SetCustomAttribute(_attributeBuilder); | |
| 128 | |
| 129 // Suppress multiple instances when the property has both getter and setter. | |
| 130 // | |
| 131 _attributeBuilder = null; | |
| 132 } | |
| 133 } | |
| 134 } | |
| 135 } | |
| 136 } |
