Home

Interesting Expression mapping question

Hi,
I'm working on an LINQ expression mapper using ExpressionVisitor. The idea is to replace an expression's sourcetype by a different type with same properties and fields (and perhaps property- and fieldnames). When I us simple types (int, string) everything works fine. But when I try to access complex properties, mapping fails with an ArgumentException(Die Eigenschaft "System.String LogisticResourceStateName" ist für den Typ "LogisticResourceStateDest" nicht definiert. ).
Any ideas why the expression isn't mapped?

Regards

Oskar


public class LogisticResourceStateSource { public long LogisticResourceStateId { get; set; } public string LogisticResourceStateName { get; set; } public ICollection<LogisticResourceSource> LogisticResources { get; set; } } public class LogisticResourceSource { public long LogisticResourceId { get; set; } public string LogisticResourceName { get; set; } public long LogisticResourceStateId { get; set; } public long LogisticResourceTypeId { get; set; } public LogisticResourceStateSource LogisticResourceState { get; set; } public LogisticResourceTypeSource LogisticResourceType { get; set; } } public class LogisticResourceTypeSource { public long LogisticResourceId { get; set; } public string LogisticResourceName { get; set; } public ICollection<LogisticResourceSource> LogisticResources { get; set; } } public class LogisticResourceStateDest { public long LogisticResourceStateId { get; set; } public string LogisticResourceStateName { get; set; } public ICollection<LogisticResourceDest> LogisticResources { get; set; } } public class LogisticResourceDest { public long LogisticResourceId { get; set; } public string LogisticResourceName { get; set; } public long LogisticResourceStateId { get; set; } public long LogisticResourceTypeId { get; set; } public LogisticResourceStateDest LogisticResourceState { get; set; } public LogisticResourceTypeDest LogisticResourceType { get; set; } } public class LogisticResourceTypeDest { public long LogisticResourceId { get; set; } public string LogisticResourceName { get; set; } public ICollection<LogisticResourceDest> LogisticResources { get; set; } } void Main() { var expression = (Expression<Func<LogisticResourceSource, bool>>)(lr => lr.LogisticResourceStateId > 1 && lr.LogisticResourceName.StartsWith("Vau") && lr.LogisticResourceState.LogisticResourceStateName.StartsWith("S")); Expression<Func<LogisticResourceDest, bool>> expressionConverted = expression.Convert<LogisticResourceSource, LogisticResourceDest, bool>( ); } public static class ExpressionNodeExtensions { /// <summary> /// The convert. /// </summary> /// <param name="expressionNode"> /// The expression node. /// </param> /// <typeparam name="TSource"> /// The source type /// </typeparam> /// <typeparam name="TDestination"> /// The destination type /// </typeparam> /// <typeparam name="TResult"> /// The result type /// </typeparam> /// <returns> /// The <see cref="Expression"/>. /// </returns> public static Expression<Func<TDestination, TResult>> Convert<TSource, TDestination, TResult>(this ExpressionNode expressionNode) { var expression = expressionNode.ToExpression(); var expressionConverter = new ExpressionConverter<TSource, TDestination, TResult>(); return (Expression<Func<TDestination, TResult>>)expressionConverter.Convert(expression); } public static Expression<Func<TDestination, TResult>> Convert<TSource, TDestination, TResult>(this Expression<Func<TSource, TResult>> expression) { var expressionConverter = new ExpressionConverter<TSource, TDestination, TResult>(); return (Expression<Func<TDestination, TResult>>)expressionConverter.Convert(expression); } } /// <summary> /// The expression converter. /// </summary> /// <typeparam name="TSource"> /// The source type of parameter to convert from /// </typeparam> /// <typeparam name="TDestination"> /// The destination type of parameter to convert to /// </typeparam> /// <typeparam name="TResult"> /// Used to specify the expected result type /// </typeparam> internal class ExpressionConverter<TSource, TDestination, TResult> : System.Linq.Expressions.ExpressionVisitor { /// <summary> /// The replace parameter. /// </summary> private ParameterExpression replaceParam; /// <summary> /// The convert. /// </summary> /// <param name="expr"> /// The expression. /// </param> /// <returns> /// The <see cref="Expression"/>. /// </returns> public Expression Convert(Expression expr) { return this.Visit(expr); } /// <summary> /// The visit lambda. /// </summary> /// <param name="node"> /// The node. /// </param> /// <typeparam name="T"> /// The Type of the expression node /// </typeparam> /// <returns> /// The <see cref="Expression"/>. /// </returns> protected override Expression VisitLambda<T>(Expression<T> node) { if (typeof(T) != typeof(Func<TSource, TResult>)) { return base.VisitLambda<T>(node); } this.replaceParam = Expression.Parameter(typeof(TDestination)); return Expression.Lambda<Func<TDestination, TResult>>(this.Visit(node.Body), this.replaceParam); } /// <summary> /// The visit parameter. /// </summary> /// <param name="node"> /// The node. /// </param> /// <returns> /// The <see cref="Expression"/>. /// </returns> protected override Expression VisitParameter(ParameterExpression node) { return node.Type == typeof(TSource) ? this.replaceParam : base.VisitParameter(node); } /// <summary> /// The visit member. /// </summary> /// <param name="node"> /// The node. /// </param> /// <returns> /// The <see cref="Expression"/>. /// </returns> /// <exception cref="InvalidOperationException"> /// Thrown if data object has no corresponding member /// </exception> protected override Expression VisitMember(MemberExpression node) { if (node.Member.DeclaringType != typeof(TSource)) { return base.VisitMember(node); } var member = typeof(TDestination).GetMember(node.Member.Name, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).FirstOrDefault(); if (member == null) { throw new InvalidOperationException("Cannot identify corresponding member of DataObject"); } //return Expression.MakeMemberAccess(this.Visit(node.Expression), member); var expression = this.Visit(node.Expression); var result = Expression.MakeMemberAccess(expression, member); return result; } }
Sign In or Register to comment.