/// <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 = typeof(Expression) .GetMethods() .First(s => s.Name == "Lambda" && s.ContainsGenericParameters); 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 }) as dynamic; var getterDelegate = getExpression.Compile(); 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 } }) as dynamic; var setterDelegate = setExpression.Compile(); 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) { 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(); Setter = new PropertyHelper <TAtt>(setMethod); ((PropertyHelper <TAtt>)Setter).SetSet(setterDelegate); } } } 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); }
/// <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 getterDelegate = Expression.Lambda(accessField); //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 setterDelegate = Expression.Lambda(setter, 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 = Expression.Lambda(accessField, thisRef); //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 = Expression.Lambda( Expression.Block(setter, returnMaybeValueType, retunLabel), thisRef, valueRef); //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 ex) { Console.WriteLine(ex); //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> >(); Getter.Init(getMethod); } if (setMethod != null) { Setter = new MethodInfoCache <TAtt, MethodArgsInfoCache <TAtt> >(); Setter.Init(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); }