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 }