/// <summary>Gets a delegate that can be invoked to add an item to a collection of the specified type.</summary> /// <param name='listType'>Type of list to use.</param> /// <returns>The delegate to invoke.</returns> internal static Action <object, object> GetAddToCollectionDelegate(Type listType) { Debug.Assert(listType != null, "listType != null"); Type listElementType; MethodInfo addMethod = ClientTypeUtil.GetAddToCollectionMethod(listType, out listElementType); ParameterExpression list = Expression.Parameter(typeof(object), "list"); ParameterExpression item = Expression.Parameter(typeof(object), "element"); Expression body = Expression.Call(Expression.Convert(list, listType), addMethod, Expression.Convert(item, listElementType)); #if ASTORIA_LIGHT LambdaExpression lambda = ExpressionHelpers.CreateLambda(body, list, item); #else LambdaExpression lambda = Expression.Lambda(body, list, item); #endif return((Action <object, object>)lambda.Compile()); }
internal ClientPropertyAnnotation(IEdmProperty edmProperty, PropertyInfo propertyInfo, DataServiceProtocolVersion maxProtocolVersion) { ParameterExpression expression; ParameterExpression expression2; this.EdmProperty = edmProperty; this.PropertyName = propertyInfo.Name; this.NullablePropertyType = propertyInfo.PropertyType; this.PropertyType = Nullable.GetUnderlyingType(this.NullablePropertyType) ?? this.NullablePropertyType; this.DeclaringClrType = propertyInfo.DeclaringType; MethodInfo getMethod = propertyInfo.GetGetMethod(); MethodInfo setMethod = propertyInfo.GetSetMethod(); this.propertyGetter = (getMethod == null) ? null : ((Func <object, object>)Expression.Lambda(Expression.Convert(Expression.Call(Expression.Convert(expression = Expression.Parameter(typeof(object), "instance"), this.DeclaringClrType), getMethod), typeof(object)), new ParameterExpression[] { expression }).Compile()); this.propertySetter = (setMethod == null) ? null : ((Action <object, object>)Expression.Lambda(Expression.Call(Expression.Convert(expression, this.DeclaringClrType), setMethod, new Expression[] { Expression.Convert(expression2 = Expression.Parameter(typeof(object), "value"), this.NullablePropertyType) }), new ParameterExpression[] { expression, expression2 }).Compile()); this.MaxProtocolVersion = maxProtocolVersion; this.IsKnownType = PrimitiveType.IsKnownType(this.PropertyType); if (!this.IsKnownType) { MethodInfo method = ClientTypeUtil.GetMethodForGenericType(this.PropertyType, typeof(IDictionary <,>), "set_Item", out this.DictionaryValueType); if (method != null) { ParameterExpression expression3; this.dictionarySetter = (Action <object, string, object>)Expression.Lambda(Expression.Call(Expression.Convert(expression, typeof(IDictionary <,>).MakeGenericType(new Type[] { typeof(string), this.DictionaryValueType })), method, expression3 = Expression.Parameter(typeof(string), "propertyName"), Expression.Convert(expression2, this.DictionaryValueType)), new ParameterExpression[] { expression, expression3, expression2 }).Compile(); } else { MethodInfo info4 = ClientTypeUtil.GetMethodForGenericType(this.PropertyType, typeof(ICollection <>), "Contains", out this.collectionGenericType); MethodInfo addToCollectionMethod = ClientTypeUtil.GetAddToCollectionMethod(this.PropertyType, out this.collectionGenericType); MethodInfo info6 = ClientTypeUtil.GetMethodForGenericType(this.PropertyType, typeof(ICollection <>), "Remove", out this.collectionGenericType); MethodInfo info7 = ClientTypeUtil.GetMethodForGenericType(this.PropertyType, typeof(ICollection <>), "Clear", out this.collectionGenericType); this.collectionContains = (info4 == null) ? null : ((Func <object, object, bool>)Expression.Lambda(Expression.Call(Expression.Convert(expression, this.PropertyType), info4, new Expression[] { Expression.Convert(expression2, this.collectionGenericType) }), new ParameterExpression[] { expression, expression2 }).Compile()); this.collectionAdd = (addToCollectionMethod == null) ? null : ((Action <object, object>)Expression.Lambda(Expression.Call(Expression.Convert(expression, this.PropertyType), addToCollectionMethod, new Expression[] { Expression.Convert(expression2, this.collectionGenericType) }), new ParameterExpression[] { expression, expression2 }).Compile()); this.collectionRemove = (info6 == null) ? null : ((Func <object, object, bool>)Expression.Lambda(Expression.Call(Expression.Convert(expression, this.PropertyType), info6, new Expression[] { Expression.Convert(expression2, this.collectionGenericType) }), new ParameterExpression[] { expression, expression2 }).Compile()); this.collectionClear = (info7 == null) ? null : ((Action <object>)Expression.Lambda(Expression.Call(Expression.Convert(expression, this.PropertyType), info7), new ParameterExpression[] { expression }).Compile()); } } }
/// <summary> /// constructor /// </summary> /// <param name="edmProperty">Back reference to the EdmProperty this annotation is part of.</param> /// <param name="propertyInfo">propertyInfo instance.</param> /// <param name="backingField">FieldInfo instance for peeking initial property values.</param> /// <param name="model">The client model.</param> internal ClientPropertyAnnotation(IEdmProperty edmProperty, PropertyInfo propertyInfo, FieldInfo backingField, ClientEdmModel model) { Debug.Assert(edmProperty != null, "edmProperty != null"); Debug.Assert(propertyInfo != null, "null propertyInfo"); // Property should always have DeclaringType Debug.Assert(propertyInfo.DeclaringType != null, "Property without a declaring type"); this.EdmProperty = edmProperty; this.PropertyName = propertyInfo.Name; this.NullablePropertyType = propertyInfo.PropertyType; this.PropertyType = Nullable.GetUnderlyingType(this.NullablePropertyType) ?? this.NullablePropertyType; this.DeclaringClrType = propertyInfo.DeclaringType; MethodInfo propertyGetMethod = propertyInfo.GetGetMethod(); // Add the parameter to make set method is returned even it is not public. Portable lib does not support this. #if PORTABLELIB MethodInfo propertySetMethod = propertyInfo.GetSetMethod(); #else MethodInfo propertySetMethod = propertyInfo.GetSetMethod(true); #endif ParameterExpression instance = Expression.Parameter(typeof(Object), "instance"); ParameterExpression value = Expression.Parameter(typeof(Object), "value"); // instance => (Object)(((T)instance).get_PropertyName()); <-- we need to box the value back to object to return this.propertyGetter = propertyGetMethod == null ? null : (Func <object, object>)Expression.Lambda( Expression.Convert( Expression.Call( Expression.Convert(instance, this.DeclaringClrType), propertyGetMethod), typeof(Object)), instance).Compile(); // (instance, value) => ((T)instance).set_PropertyName((T1)value); this.propertySetter = propertySetMethod == null ? null : (Action <object, object>)Expression.Lambda( Expression.Call( Expression.Convert(instance, this.DeclaringClrType), propertySetMethod, Expression.Convert(value, this.NullablePropertyType)), instance, value).Compile(); if (backingField == null) { this.fieldOrPropertyGetter = propertyGetter; } else { this.fieldOrPropertyGetter = (Func <object, object>)Expression.Lambda( Expression.Convert( Expression.Field( Expression.Convert(instance, this.DeclaringClrType), backingField), typeof(Object)), instance).Compile(); } this.Model = model; this.IsKnownType = PrimitiveType.IsKnownType(this.PropertyType); // non primitive types: dictionary/collections if (!this.IsKnownType) { var setMethodInfo = ClientTypeUtil.GetMethodForGenericType(this.PropertyType, typeof(IDictionary <,>), "set_Item", out this.DictionaryValueType); if (setMethodInfo != null) { ParameterExpression propertyNameParam = Expression.Parameter(typeof(String), "propertyName"); // (instance, propertyName, value) => ((IDictionary<string, DictionaryValueType>)instance)[propertyName] = (DictionaryValueType)value; this.dictionarySetter = (Action <Object, String, Object>)Expression.Lambda( Expression.Call( Expression.Convert(instance, typeof(IDictionary <,>).MakeGenericType(typeof(String), this.DictionaryValueType)), setMethodInfo, propertyNameParam, Expression.Convert(value, this.DictionaryValueType)), instance, propertyNameParam, value).Compile(); } else { var containsMethod = ClientTypeUtil.GetMethodForGenericType(this.PropertyType, typeof(ICollection <>), "Contains", out this.collectionGenericType); var addMethod = ClientTypeUtil.GetAddToCollectionMethod(this.PropertyType, out this.collectionGenericType); var removeMethod = ClientTypeUtil.GetMethodForGenericType(this.PropertyType, typeof(ICollection <>), "Remove", out this.collectionGenericType); var clearMethod = ClientTypeUtil.GetMethodForGenericType(this.PropertyType, typeof(ICollection <>), "Clear", out this.collectionGenericType); // (instance, value) => ((PropertyType)instance).Contains((CollectionType)value); returns boolean this.collectionContains = containsMethod == null ? null : (Func <Object, Object, Boolean>)Expression.Lambda( Expression.Call( Expression.Convert(instance, this.PropertyType), containsMethod, Expression.Convert(value, this.collectionGenericType)), instance, value).Compile(); // (instance, value) => ((PropertyType)instance).Add((CollectionType)value); this.collectionAdd = addMethod == null ? null : (Action <Object, Object>)Expression.Lambda( Expression.Call( Expression.Convert(instance, this.PropertyType), addMethod, Expression.Convert(value, this.collectionGenericType)), instance, value).Compile(); // (instance, value) => ((PropertyType)instance).Remove((CollectionType)value); returns boolean this.collectionRemove = removeMethod == null ? null : (Func <Object, Object, Boolean>)Expression.Lambda( Expression.Call( Expression.Convert(instance, this.PropertyType), removeMethod, Expression.Convert(value, this.collectionGenericType)), instance, value).Compile(); // (instance) => ((PropertyType)instance).Clear(); this.collectionClear = clearMethod == null ? null : (Action <Object>)Expression.Lambda( Expression.Call( Expression.Convert(instance, this.PropertyType), clearMethod), instance).Compile(); } } Debug.Assert(this.collectionGenericType == null || this.DictionaryValueType == null, "collectionGenericType and DictionaryItemType mutually exclusive. (They both can be null though)."); }