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 } |