annotate Source/TypeBuilder/Builders/GeneratedAttributeBuilder.cs @ 0:f990fcb411a9

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