gpt4 book ai didi

c# - 如何更正表达式的替换类型?

转载 作者:行者123 更新时间:2023-11-30 12:58:13 24 4
gpt4 key购买 nike

我有两个类:

public class DalMembershipUser
{
public string UserName { get; set; }
//other members
}

public class MembershipUser
{
public string UserName { get; set; }
//other members
}

我有函数:

    public IEnumerable<DalMembershipUser> GetMany(Expression<Func<DalMembershipUser, bool>> predicate)
{
//but here i can use only Func<MembershipUser, bool>
//so i made transformation
query = query.Where(ExpressionTransformer<DalMembershipUser,MembershipUser>.Tranform(predicate));
}

当前实现:

public static class ExpressionTransformer<TFrom, TTo>
{
public class Visitor : ExpressionVisitor
{
private ParameterExpression _targetParameterExpression;

public Visitor(ParameterExpression parameter)
{
_targetParameterExpression = parameter;
}

protected override Expression VisitParameter(ParameterExpression node)
{
return _targetParameterExpression;
}
}

public static Expression<Func<TTo, bool>> Tranform(Expression<Func<TFrom, bool>> expression)
{
ParameterExpression parameter = Expression.Parameter(typeof(TTo), expression.Parameters[0].Name);
Expression body = expression.Body;
new Visitor(parameter).Visit(expression.Body);
return Expression.Lambda<Func<TTo, bool>>(body, parameter);
}
}

//某处:.GetMany(u => u.UserName == "username");

异常:未为类型“MembershipUser”定义属性“System.String UserName”
在行:new Visitor(parameter).Visit(expression.Body);

最佳答案

终于成功了。但是仍然不明白为什么要创建清晰的参数:Expression.Parameter(typeof(TTo), from.Parameters[i].Name); 无效,需要提取。

public static class ExpressionHelper
{

public static Expression<Func<TTo, bool>> TypeConvert<TFrom, TTo>(
this Expression<Func<TFrom, bool>> from)
{
if (from == null) return null;

return ConvertImpl<Func<TFrom, bool>, Func<TTo, bool>>(from);
}

private static Expression<TTo> ConvertImpl<TFrom, TTo>(Expression<TFrom> from)
where TFrom : class
where TTo : class
{
// figure out which types are different in the function-signature

var fromTypes = from.Type.GetGenericArguments();
var toTypes = typeof(TTo).GetGenericArguments();

if (fromTypes.Length != toTypes.Length)
throw new NotSupportedException("Incompatible lambda function-type signatures");

Dictionary<Type, Type> typeMap = new Dictionary<Type, Type>();
for (int i = 0; i < fromTypes.Length; i++)
{
if (fromTypes[i] != toTypes[i])
typeMap[fromTypes[i]] = toTypes[i];
}

// re-map all parameters that involve different types
Dictionary<Expression, Expression> parameterMap = new Dictionary<Expression, Expression>();
ParameterExpression[] newParams = GenerateParameterMap<TFrom>(from, typeMap, parameterMap);

// rebuild the lambda
var body = new TypeConversionVisitor<TTo>(parameterMap).Visit(from.Body);
return Expression.Lambda<TTo>(body, newParams);
}

private static ParameterExpression[] GenerateParameterMap<TFrom>(
Expression<TFrom> from,
Dictionary<Type, Type> typeMap,
Dictionary<Expression, Expression> parameterMap
)
where TFrom : class
{
var newParams = new ParameterExpression[from.Parameters.Count];

for (int i = 0; i < newParams.Length; i++)
{
Type newType;
if (typeMap.TryGetValue(from.Parameters[i].Type, out newType))
{
parameterMap[from.Parameters[i]] = newParams[i] = Expression.Parameter(newType, from.Parameters[i].Name);
}
}
return newParams;
}


class TypeConversionVisitor<T> : ExpressionVisitor
{
private readonly Dictionary<Expression, Expression> parameterMap;

public TypeConversionVisitor(Dictionary<Expression, Expression> parameterMap)
{
this.parameterMap = parameterMap;
}

protected override Expression VisitParameter(ParameterExpression node)
{
// re-map the parameter
Expression found;
if (!parameterMap.TryGetValue(node, out found))
found = base.VisitParameter(node);
return found;
}
public override Expression Visit(Expression node)
{
LambdaExpression lambda = node as LambdaExpression;
if (lambda != null && !parameterMap.ContainsKey(lambda.Parameters.First()))
{
return new TypeConversionVisitor<T>(parameterMap).Visit(lambda.Body);
}
return base.Visit(node);
}

protected override Expression VisitMember(MemberExpression node)
{
// re-perform any member-binding
var expr = Visit(node.Expression);
if (expr.Type != node.Type)
{
if (expr.Type.GetMember(node.Member.Name).Any())
{
MemberInfo newMember = expr.Type.GetMember(node.Member.Name).Single();
return Expression.MakeMemberAccess(expr, newMember);
}
}
return base.VisitMember(node);
}
}
}

关于c# - 如何更正表达式的替换类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30537877/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com