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