Mercurial > pub > bltoolkit
comparison Source/Reflection/ExprTypeAccessor.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.Linq; | |
3 using System.Collections.Generic; | |
4 using System.Linq.Expressions; | |
5 using System.Reflection; | |
6 | |
7 namespace BLToolkit.Reflection | |
8 { | |
9 using TypeBuilder; | |
10 | |
11 class ExprTypeAccessor<T,TOriginal> : TypeAccessor | |
12 { | |
13 static ExprTypeAccessor() | |
14 { | |
15 // Create Instance. | |
16 // | |
17 var type = typeof(T); | |
18 var typeInit = typeof(InitContext); | |
19 var initPar = Expression.Parameter(typeInit, "ctx"); | |
20 | |
21 if (type.IsValueType) | |
22 { | |
23 _createInstance = () => default(T); | |
24 _createInstanceInit = ctx => default(T); | |
25 } | |
26 else | |
27 { | |
28 var ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes, null); | |
29 var ctorInit = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new[] { typeInit }, null); | |
30 | |
31 if (ctor == null && ctorInit == null) | |
32 { | |
33 Expression<Func<T>> mi = () => ThrowException(); | |
34 | |
35 var body = Expression.Call(null, ((MethodCallExpression)mi.Body).Method); | |
36 | |
37 _createInstance = Expression.Lambda<Func<T>>(body).Compile(); | |
38 _createInstanceInit = Expression.Lambda<Func<InitContext, T>>(body, initPar).Compile(); | |
39 } | |
40 else | |
41 { | |
42 _createInstance = ctor != null ? | |
43 Expression.Lambda<Func<T>>(Expression.New(ctor)).Compile() : | |
44 Expression.Lambda<Func<T>>(Expression.New(ctorInit, Expression.Constant(null))).Compile(); | |
45 | |
46 _createInstanceInit = ctorInit != null ? | |
47 Expression.Lambda<Func<InitContext, T>>(Expression.New(ctorInit, initPar), initPar).Compile() : | |
48 Expression.Lambda<Func<InitContext, T>>(Expression.New(ctor), initPar).Compile(); | |
49 } | |
50 } | |
51 | |
52 var originalType = typeof(TOriginal); | |
53 | |
54 // Add fields. | |
55 // | |
56 foreach (var fi in originalType.GetFields(BindingFlags.Instance | BindingFlags.Public)) | |
57 _members.Add(fi); | |
58 | |
59 foreach (var pi in originalType.GetProperties(BindingFlags.Instance | BindingFlags.Public)) | |
60 if (pi.GetIndexParameters().Length == 0) | |
61 _members.Add(pi); | |
62 | |
63 // Add explicit iterface implementation properties support | |
64 // Or maybe we should support all private fields/properties? | |
65 var interfaceMethods = originalType.GetInterfaces().SelectMany(ti => originalType.GetInterfaceMap(ti).TargetMethods).ToList(); | |
66 | |
67 if (interfaceMethods.Count > 0) | |
68 { | |
69 foreach (var pi in originalType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)) | |
70 { | |
71 if (pi.GetIndexParameters().Length == 0) | |
72 { | |
73 var getMethod = pi.GetGetMethod(true); | |
74 var setMethod = pi.GetSetMethod(true); | |
75 | |
76 if ((getMethod == null || interfaceMethods.Contains(getMethod)) && | |
77 (setMethod == null || interfaceMethods.Contains(setMethod))) | |
78 { | |
79 _members.Add(pi); | |
80 } | |
81 } | |
82 } | |
83 } | |
84 | |
85 // ObjectFactory | |
86 // | |
87 var attr = TypeHelper.GetFirstAttribute(type, typeof(ObjectFactoryAttribute)); | |
88 | |
89 if (attr != null) | |
90 _objectFactory = ((ObjectFactoryAttribute)attr).ObjectFactory; | |
91 } | |
92 | |
93 static T ThrowException() | |
94 { | |
95 throw new TypeBuilderException(string.Format("The '{0}' type must have default or init constructor.", typeof(TOriginal).FullName)); | |
96 } | |
97 | |
98 static readonly List<MemberInfo> _members = new List<MemberInfo>(); | |
99 static readonly IObjectFactory _objectFactory; | |
100 | |
101 public ExprTypeAccessor() | |
102 { | |
103 foreach (var member in _members) | |
104 AddMember(ExprMemberAccessor.GetMemberAccessor(this, member.Name)); | |
105 | |
106 ObjectFactory = _objectFactory; | |
107 } | |
108 | |
109 static readonly Func<T> _createInstance; | |
110 public override object CreateInstance() | |
111 { | |
112 return _createInstance(); | |
113 } | |
114 | |
115 static readonly Func<InitContext,T> _createInstanceInit; | |
116 | |
117 public override object CreateInstance(InitContext context) | |
118 { | |
119 return _createInstanceInit(context); | |
120 } | |
121 | |
122 public override Type Type { get { return typeof(T); } } | |
123 public override Type OriginalType { get { return typeof(TOriginal); } } | |
124 } | |
125 } |