private static PropertyDictionaryDelegate CreateDelegateForType(Type objectType, PropertyCasing casing) { // the parameter to call the method on var inputObject = Expression.Parameter(typeof(object), "inputObject"); var treeParameter = Expression.Parameter(typeof(ImmutableHashTree <string, object>), "tree"); // loval variable of type declaringType var tVariable = Expression.Variable(objectType); // cast the input object to be declaring type Expression castExpression = Expression.Convert(inputObject, objectType); // assign the cast value to the tVaraible variable Expression assignmentExpression = Expression.Assign(tVariable, castExpression); // keep a list of the variable we declare for use when we define the body var variableList = new List <ParameterExpression> { tVariable }; var bodyExpressions = new List <Expression> { assignmentExpression }; var updateDelegate = Expression.Constant( new ImmutableHashTree <string, object> .UpdateDelegate((oldValue, newValue) => newValue)); Expression tree = treeParameter; foreach (var property in objectType.GetTypeInfo().DeclaredProperties) { if (property.CanRead && !property.GetMethod.IsStatic && property.GetMethod.IsPublic && property.GetMethod.GetParameters().Length == 0) { var propertyAccess = Expression.Property(tVariable, property.GetMethod); var propertyCast = Expression.Convert(propertyAccess, typeof(object)); var propertyName = property.Name; switch (casing) { case PropertyCasing.Lower: propertyName = propertyName.ToLowerInvariant(); break; case PropertyCasing.Upper: propertyName = propertyName.ToUpperInvariant(); break; } tree = Expression.Call(tree, ImmutableTreeAdd, Expression.Constant(propertyName), propertyCast, updateDelegate); } } bodyExpressions.Add(tree); var body = Expression.Block(variableList, bodyExpressions); return(Expression.Lambda <PropertyDictionaryDelegate>(body, inputObject, treeParameter).Compile()); }
/// <summary> /// Get dictionary of property values from an object /// </summary> /// <param name="annonymousObject">object to get properties from</param> /// <param name="values">collection to add to</param> /// <param name="casing">lowercase property names</param> /// <returns></returns> public static ImmutableHashTree <string, object> GetPropertiesFromObject(object annonymousObject, ImmutableHashTree <string, object> values = null, PropertyCasing casing = PropertyCasing.Default) { values = values ?? ImmutableHashTree <string, object> .Empty; if (annonymousObject == null) { return(values); } var array = annonymousObject as Array; if (array != null) { var i = 0; foreach (var value in array) { values = values.Add(i.ToString(), value); i++; } return(values); } var dictionary = annonymousObject as IDictionary <string, object>; if (dictionary != null) { return(dictionary.Aggregate(values, (v, kvp) => v.Add(kvp.Key, kvp.Value))); } var objectType = annonymousObject.GetType(); PropertyDictionaryDelegate propertyDelegate = null; switch (casing) { case PropertyCasing.Default: propertyDelegate = _propertyDelegates.GetValueOrDefault(objectType); break; case PropertyCasing.Lower: propertyDelegate = _lowerCasePropertyDelegates.GetValueOrDefault(objectType); break; case PropertyCasing.Upper: propertyDelegate = _upperCasePropertyDelegates.GetValueOrDefault(objectType); break; } if (propertyDelegate != null) { return(propertyDelegate(annonymousObject, values)); } propertyDelegate = CreateDelegateForType(objectType, casing); switch (casing) { case PropertyCasing.Default: _propertyDelegates = _propertyDelegates.Add(objectType, propertyDelegate); break; case PropertyCasing.Lower: _lowerCasePropertyDelegates = _lowerCasePropertyDelegates.Add(objectType, propertyDelegate); break; case PropertyCasing.Upper: _upperCasePropertyDelegates = _upperCasePropertyDelegates.Add(objectType, propertyDelegate); break; } return(propertyDelegate(annonymousObject, values)); }