annotate Source/Reflection/ExprTypeAccessor.cs @ 6:11b6da379593

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