internal static Func <TParent, IEnumerable <TChild> > CreatePropertySetup <TParent, TChild>(this Type itemType, string propertyName) //where TParent : class //where TChild : class { var key = new PropertySetterKey(itemType, typeof(TChild), propertyName); var setter = _collectionInitialiserCache.GetOrAdd(key, k => { var pi = itemType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance); var tChildType = pi.PropertyType; var parentParam = Expression.Parameter(itemType, "p"); var property = Expression.Property(parentParam, propertyName); var isParamNull = Expression.Equal(property, Expression.Constant(null)); var collectionTypeToCreate = GetTypeToCreate(tChildType); if (collectionTypeToCreate.GetConstructor(Type.EmptyTypes) == null) { throw new ArgumentException("Collection must have a parameterless constructor. Try instantiating " + "the item in the owners ctor"); } Expression newCollection = null; if (collectionTypeToCreate.IsGenericTypeDefinition) { newCollection = Expression.New(collectionTypeToCreate.MakeGenericType(new Type[] { typeof(TChild) })); } else { newCollection = Expression.New(collectionTypeToCreate); } var mi = pi.GetSetMethod(); var mce = Expression.Call(parentParam, mi, newCollection); var @if = Expression.IfThen(isParamNull, mce); var expressions = new List <Expression> { @if }; var returnTarget = Expression.Label(typeof(IEnumerable <TChild>)); expressions.Add(Expression.Return(returnTarget, property, typeof(IEnumerable <TChild>))); expressions.Add(Expression.Label(returnTarget, Expression.Constant(default(IEnumerable <TChild>), typeof(IEnumerable <TChild>)))); var block = Expression.Block(expressions); var finalCode = Expression.Lambda <Func <TParent, IEnumerable <TChild> > >(block, parentParam); return(new CollectionInitializer <TParent, TChild>(finalCode.Compile())); }); var typesSetter = setter as CollectionInitializer <TParent, TChild>; return(typesSetter?.Initializer); }
public static object GetPropertySetter(Type tObject, Type tProperty, string propertyName) { var key = new PropertySetterKey(tObject, propertyName); if (Setters.TryGetValue(key, out object propertySetter)) { return(propertySetter); } return(ReflectionUtils .GetMethod(() => GetPropertySetter <object, object>(""), tObject, tProperty) .Invoke(null, new object[] { propertyName })); }
public static PropertySetter <TObject> GetPropertySetter <TObject, TProperty>(string propertyName) { var key = new PropertySetterKey(typeof(TObject), propertyName); if (Setters.TryGetValue(key, out object propertySetter)) { return((PropertySetter <TObject>)propertySetter); } var propertySetter2 = BuildPropertySetter <TObject, TProperty>(propertyName); Setters.GetOrAdd(key, propertySetter2); return(propertySetter2); }
internal static Action <TElement, TValue> CreatePropertySetter <TElement, TValue>( this Type elementType, string propertyName) { var key = new PropertySetterKey(elementType, typeof(TValue), propertyName); var setter = _propertySetterCache.GetOrAdd(key, k => { var pi = k.ElementType.GetProperty(k.PropertyName, BindingFlags.Public | BindingFlags.Instance); var mi = pi.GetSetMethod(); var oParam = Expression.Parameter(k.ElementType, "obj"); var vParam = Expression.Parameter(k.ValueType, "val"); var mce = Expression.Call(oParam, mi, vParam); var action = Expression.Lambda <Action <TElement, TValue> >(mce, oParam, vParam); return(new PropertySetterCache <TElement, TValue>(action.Compile())); }); var typedSetter = setter as PropertySetterCache <TElement, TValue>; return(typedSetter?.Setter); }
internal static Action <TElement, TValue> CreateCollectionPropertySetter <TElement, TValue>( this Type elementType, string propertyName, Type propertyType) { var key = new PropertySetterKey(elementType, typeof(TValue), propertyName); var setter = _collectionSetterCache.GetOrAdd(key, k => { var oParam = Expression.Parameter(k.ElementType, "obj"); var vParam = Expression.Parameter(k.ValueType, "val"); var mce = Expression.Call( Expression.Convert( Expression.Property(oParam, k.PropertyName) , typeof(ICollection <TValue>)) , typeof(ICollection <TValue>).GetMethod("Add"), vParam); var action = Expression.Lambda <Action <TElement, TValue> >(mce, oParam, vParam); return(new PropertySetterCache <TElement, TValue>(action.Compile())); }); var typedSetter = setter as PropertySetterCache <TElement, TValue>; return(typedSetter?.Setter); }