Exemplo n.º 1
0
        public virtual IClassInfoCache <TProp, TAttr, TMeth, TCtor, TArg> Init(Type type, bool anon = false)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (!String.IsNullOrEmpty(Name))
            {
                throw new InvalidOperationException("The object is already Initialed. A Change is not allowed");
            }

            Name = type.FullName;
            Type = type;

            if (Type.IsInterface)
            {
                anon = true;
            }

            foreach (var attributeInfoCach in type
                     .GetCustomAttributes(true)
                     .Where(s => s is Attribute)
                     .Select(s => new TAttr().Init(s as Attribute) as TAttr))
            {
                Attributes.Add(attributeInfoCach);
            }
            foreach (var propertyInfoCach in type
                     .GetProperties(BindingFlags.Public | BindingFlags.Static |
                                    BindingFlags.NonPublic | BindingFlags.Instance)
                     .Where(e => !e.GetIndexParameters().Any())
                     .Select(s => new TProp().Init(s, anon) as TProp)
                     .ToDictionary(s => s.PropertyName, s => s))
            {
                Propertys.Add(propertyInfoCach.Key, propertyInfoCach.Value);
            }

            foreach (var methodInfoCach in type
                     .GetMethods(BindingFlags.Public | BindingFlags.Static |
                                 BindingFlags.NonPublic | BindingFlags.Instance)
                     .Select(s => new TMeth().Init(s) as TMeth))
            {
                Mehtods.Add(methodInfoCach);
            }

            foreach (var constructor in type
                     .GetConstructors(BindingFlags.Public | BindingFlags.Static |
                                      BindingFlags.NonPublic | BindingFlags.Instance)
                     .Select(s => new TCtor().Init(s) as TCtor))
            {
                Constructors.Add(constructor);
            }
            var defaultConstructor = Constructors.FirstOrDefault(f => !f.Arguments.Any());

            IsMsCoreFrameworkType = type.Assembly == MsCoreLibAssembly;

            //if (type.IsValueType)
            //{
            //	var dm = new DynamicMethod("InvokeDefaultCtorFor" + ClassName, Type, System.Type.EmptyTypes, Type, true);
            //	var il = dm.GetILGenerator();
            //	il.Emit(OpCodes.Initobj, type);
            //	var ctorDelegate = dm.CreateDelegate(typeof(Func<>).MakeGenericType(type));
            //	DefaultFactory = new TMeth().Init(ctorDelegate.Method, type) as TMeth;
            //}
            //else if (defaultConstructor != null)
            //{
            //	var dm = new DynamicMethod("InvokeDefaultCtorFor" + ClassName, Type, System.Type.EmptyTypes, Type, true);
            //	var il = dm.GetILGenerator();
            //	il.Emit(OpCodes.Newobj);
            //	var ctorDelegate = dm.CreateDelegate(typeof(Func<>).MakeGenericType(type));
            //	DefaultFactory = new TMeth().Init(ctorDelegate.Method, type) as TMeth;
            //}

            if (type.IsValueType || defaultConstructor != null)
            {
                Expression defaultExpression = null;

                if (type.IsValueType)
                {
                    defaultExpression = Expression.Default(type);
                }
                else if (defaultConstructor != null)
                {
                    defaultExpression = Expression.New(defaultConstructor.MethodInfo as ConstructorInfo);
                }

                var expressionInvoker = MetaInfoStoreExtentions.GetExpressionLambda();

                var createLambda = expressionInvoker
                                   .MakeGenericMethod(typeof(Func <>).MakeGenericType(type))
                                   .Invoke(null, new object[] { defaultExpression, new List <ParameterExpression>() });

                DefaultFactory = MetaInfoStoreExtentions.GetCompileMethodFromExpression(createLambda.GetType())
                                 .Invoke(createLambda, null);
            }

            return(this);
        }
Exemplo n.º 2
0
        /// <summary>
        ///     Internal use Only
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <param name="anon"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException">The object is already Initialed. A Change is not allowed</exception>
        public virtual IPropertyInfoCache <TAtt> Init(PropertyInfo propertyInfo, bool anon)
        {
            if (!string.IsNullOrEmpty(PropertyName))
            {
                throw new InvalidOperationException("The object is already Initialed. A Change is not allowed");
            }

            Attributes.Clear();
            if (propertyInfo == null)
            {
                return(this);
            }

            var getMethod = propertyInfo.GetMethod;
            var setMethod = propertyInfo.SetMethod;

            PropertyInfo = propertyInfo;
            PropertyName = propertyInfo.Name;
            PropertyType = propertyInfo.PropertyType;

            if (!anon && (getMethod != null || setMethod != null))
            {
                var isStatic = getMethod != null
                                        ? getMethod.Attributes.HasFlag(MethodAttributes.Static)
                                        : setMethod.Attributes.HasFlag(MethodAttributes.Static);

                var builder = MetaInfoStoreExtentions.GetExpressionLambda();

                if (isStatic)
                {
                    GetterDelegate = typeof(Func <>).MakeGenericType(propertyInfo.PropertyType);
                    SetterDelegate = typeof(Action <>).MakeGenericType(propertyInfo.PropertyType);
                    var accessField = Expression.Property(null, propertyInfo);

                    if (getMethod != null)
                    {
                        var getExpression = builder
                                            .MakeGenericMethod(GetterDelegate)
                                            .Invoke(null, new object[]
                        {
                            accessField, null
                        });

                        var getterDelegate = MetaInfoStoreExtentions
                                             .GetCompileMethodFromExpression(getExpression.GetType())
                                             .Invoke(getExpression, null);

                        Getter = new PropertyHelper <TAtt>(getMethod);
                        ((PropertyHelper <TAtt>)Getter).SetGet(getterDelegate);
                    }

                    if (setMethod != null)
                    {
                        var valueRef = Expression.Parameter(propertyInfo.PropertyType, "newValue");
                        var setter   = Expression.Assign(
                            accessField,
                            valueRef);

                        var setExpression = builder
                                            .MakeGenericMethod(SetterDelegate)
                                            .Invoke(null, new object[]
                        {
                            setter,
                            new[]
                            {
                                valueRef
                            }
                        });

                        var setterDelegate = MetaInfoStoreExtentions
                                             .GetCompileMethodFromExpression(setExpression.GetType())
                                             .Invoke(setExpression, null);

                        Setter = new PropertyHelper <TAtt>(setMethod);
                        ((PropertyHelper <TAtt>)Setter).SetSet(setterDelegate);
                    }
                }
                else
                {
                    GetterDelegate =
                        typeof(Func <,>).MakeGenericType(propertyInfo.DeclaringType, propertyInfo.PropertyType);
                    SetterDelegate = typeof(Func <, ,>).MakeGenericType(propertyInfo.DeclaringType,
                                                                        propertyInfo.PropertyType,
                                                                        propertyInfo.DeclaringType);
                    var thisRef = Expression.Parameter(propertyInfo.DeclaringType, "that");

                    var accessField = Expression.MakeMemberAccess(thisRef, propertyInfo);

                    if (getMethod != null)
                    {
                        var getExpression = builder
                                            .MakeGenericMethod(GetterDelegate)
                                            .Invoke(null, new object[]
                        {
                            accessField,
                            new[] { thisRef }
                        }) as dynamic;

                        var getterDelegate = getExpression.Compile();
                        Getter = new PropertyHelper <TAtt>(getMethod);
                        ((PropertyHelper <TAtt>)Getter).SetGet(getterDelegate);
                    }

                    if (setMethod != null)
                    {
                        Setter = new PropertyHelper <TAtt>(setMethod);
                        try
                        {
                            var valueRef = Expression.Parameter(propertyInfo.PropertyType, "newValue");
                            var setter   = Expression.Assign(
                                accessField,
                                valueRef);
                            var makeRetunLabel = Expression.Label(propertyInfo.DeclaringType);
                            var retunLabel     = Expression.Label(makeRetunLabel,
                                                                  Expression.Default(propertyInfo.DeclaringType));
                            var returnMaybeValueType = Expression.Return(makeRetunLabel, thisRef);

                            var setExpression = builder
                                                .MakeGenericMethod(SetterDelegate)
                                                .Invoke(null, new object[]
                            {
                                Expression.Block(setter, returnMaybeValueType, retunLabel),
                                new[] { thisRef, valueRef }
                            }) as dynamic;

                            var setterDelegate = setExpression.Compile();
                            ((PropertyHelper <TAtt>)Setter).SetSet(setterDelegate);
                        }
                        catch (Exception)
                        {
                            //sometimes the Compile method does throw an error. In this case fall back to reflection
                            var setDelegate = setMethod.CreateDelegate(SetterDelegate);
                            ((PropertyHelper <TAtt>)Setter).SetSet(setDelegate);
                        }
                    }
                }
            }
            else
            {
                if (getMethod != null)
                {
                    Getter = new MethodInfoCache <TAtt, MethodArgsInfoCache <TAtt> >(getMethod);
                }

                if (setMethod != null)
                {
                    Setter = new MethodInfoCache <TAtt, MethodArgsInfoCache <TAtt> >(setMethod);
                }
            }

            Attributes = new HashSet <TAtt>(propertyInfo
                                            .GetCustomAttributes(true)
                                            .Where(s => s is Attribute)
                                            .Select(s => new TAtt().Init(s as Attribute) as TAtt));

            return(this);
        }