Mercurial > pub > bltoolkit
view Source/Reflection/ExprTypeAccessor.cs @ 5:f7d63a092920
Исправлено условие Where в тех случаях, когда репозитарий не является генериком
author | cin |
---|---|
date | Tue, 10 Mar 2015 16:02:11 +0300 |
parents | f990fcb411a9 |
children |
line wrap: on
line source
using System; using System.Linq; using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; namespace BLToolkit.Reflection { using TypeBuilder; class ExprTypeAccessor<T,TOriginal> : TypeAccessor { static ExprTypeAccessor() { // Create Instance. // var type = typeof(T); var typeInit = typeof(InitContext); var initPar = Expression.Parameter(typeInit, "ctx"); if (type.IsValueType) { _createInstance = () => default(T); _createInstanceInit = ctx => default(T); } else { var ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes, null); var ctorInit = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new[] { typeInit }, null); if (ctor == null && ctorInit == null) { Expression<Func<T>> mi = () => ThrowException(); var body = Expression.Call(null, ((MethodCallExpression)mi.Body).Method); _createInstance = Expression.Lambda<Func<T>>(body).Compile(); _createInstanceInit = Expression.Lambda<Func<InitContext, T>>(body, initPar).Compile(); } else { _createInstance = ctor != null ? Expression.Lambda<Func<T>>(Expression.New(ctor)).Compile() : Expression.Lambda<Func<T>>(Expression.New(ctorInit, Expression.Constant(null))).Compile(); _createInstanceInit = ctorInit != null ? Expression.Lambda<Func<InitContext, T>>(Expression.New(ctorInit, initPar), initPar).Compile() : Expression.Lambda<Func<InitContext, T>>(Expression.New(ctor), initPar).Compile(); } } var originalType = typeof(TOriginal); // Add fields. // foreach (var fi in originalType.GetFields(BindingFlags.Instance | BindingFlags.Public)) _members.Add(fi); foreach (var pi in originalType.GetProperties(BindingFlags.Instance | BindingFlags.Public)) if (pi.GetIndexParameters().Length == 0) _members.Add(pi); // Add explicit iterface implementation properties support // Or maybe we should support all private fields/properties? var interfaceMethods = originalType.GetInterfaces().SelectMany(ti => originalType.GetInterfaceMap(ti).TargetMethods).ToList(); if (interfaceMethods.Count > 0) { foreach (var pi in originalType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)) { if (pi.GetIndexParameters().Length == 0) { var getMethod = pi.GetGetMethod(true); var setMethod = pi.GetSetMethod(true); if ((getMethod == null || interfaceMethods.Contains(getMethod)) && (setMethod == null || interfaceMethods.Contains(setMethod))) { _members.Add(pi); } } } } // ObjectFactory // var attr = TypeHelper.GetFirstAttribute(type, typeof(ObjectFactoryAttribute)); if (attr != null) _objectFactory = ((ObjectFactoryAttribute)attr).ObjectFactory; } static T ThrowException() { throw new TypeBuilderException(string.Format("The '{0}' type must have default or init constructor.", typeof(TOriginal).FullName)); } static readonly List<MemberInfo> _members = new List<MemberInfo>(); static readonly IObjectFactory _objectFactory; public ExprTypeAccessor() { foreach (var member in _members) AddMember(ExprMemberAccessor.GetMemberAccessor(this, member.Name)); ObjectFactory = _objectFactory; } static readonly Func<T> _createInstance; public override object CreateInstance() { return _createInstance(); } static readonly Func<InitContext,T> _createInstanceInit; public override object CreateInstance(InitContext context) { return _createInstanceInit(context); } public override Type Type { get { return typeof(T); } } public override Type OriginalType { get { return typeof(TOriginal); } } } }