private Action <object, object> GenerateSetter(MaterializerPathInfo pathInfo) { var targetParameter = Expression.Parameter(typeof(object)); var valueParameter = Expression.Parameter(typeof(object)); var currentExpression = (Expression)targetParameter; var lastMember = default(MemberInfo); for (var i = 0; i < pathInfo.Path.Length; i++) { var member = pathInfo.Path[i]; if (!member.DeclaringType.IsAssignableFrom(currentExpression.Type)) { currentExpression = Expression.Convert(currentExpression, member.DeclaringType); } if (i + 1 == pathInfo.Path.Length) { currentExpression = Expression.MakeMemberAccess(currentExpression, member = GetMemberForWrite(member)); } else { currentExpression = Expression.MakeMemberAccess(currentExpression, member = GetMemberForRead(member)); } lastMember = member; } Expression body = default; if (lastMember is FieldInfo field && field.IsInitOnly) { body = Expression.Call( Expression.Constant(field), typeof(FieldInfo).GetRuntimeMethod(nameof(FieldInfo.SetValue), new[] { typeof(object), typeof(object) }), (currentExpression as MemberExpression).Expression, Expression.Convert(valueParameter, currentExpression.Type)); }
private Func <object, object> GenerateGetter(MaterializerPathInfo pathInfo) { var blockVariables = new List <ParameterExpression>(); var blockExpressions = new List <Expression>(); var parameter = Expression.Parameter(typeof(object)); var currentExpression = (Expression)parameter; var returnLabel = Expression.Label(typeof(object), "Return"); var nullConstantExpression = Expression.Constant(null, typeof(object)); for (var i = 0; i < pathInfo.Path.Length; i++) { var member = pathInfo.Path[i]; var memberType = member.GetMemberType(); var memberVariable = Expression.Variable(memberType, member.Name); blockVariables.Add(memberVariable); /*if (member.DeclaringType.IsGenericType(typeof(ExpandedGrouping<,>))) * { * Debug.Assert(member == pathInfo.Path.Last()); * * if (member.Name == "Elements") * { * blockExpressions.Add( * Expression.IfThen( * Expression.Not(Expression.TypeIs(currentExpression, member.DeclaringType)), * Expression.Return(returnLabel, currentExpression))); * } * else * { * member = member.DeclaringType.FindGenericType(typeof(IGrouping<,>)).GetRuntimeProperty("Key"); * } * }*/ if (!member.DeclaringType.IsAssignableFrom(currentExpression.Type)) { currentExpression = Expression.TypeAs(currentExpression, member.DeclaringType); } blockExpressions.Add( Expression.IfThen( Expression.Equal(nullConstantExpression, currentExpression), Expression.Return(returnLabel, Expression.Default(memberType)))); blockExpressions.Add( Expression.Assign( memberVariable, Expression.MakeMemberAccess(currentExpression, GetMemberForRead(member)))); currentExpression = memberVariable; } blockExpressions.Add(Expression.Label(returnLabel, currentExpression)); return(Expression .Lambda <Func <object, object> >( Expression.Block(blockVariables, blockExpressions), parameter) .Compile()); }