表达式树复制或转换

发布于 2024-10-10 09:26:20 字数 291 浏览 6 评论 0原文

如何将 Form 的 ExpressionTree 转换

Expression<Func<POCO1, bool>> exp = p => p.Age > 50;

Expression<Func<POCO2, bool>> exp2 = p => p.Age > 50;

其中 POCO1 和 POCO2 是 C# 对象并且都具有 Int32 Age 属性

How to convert a ExpressionTree of form

Expression<Func<POCO1, bool>> exp = p => p.Age > 50;

to

Expression<Func<POCO2, bool>> exp2 = p => p.Age > 50;

where POCO1 and POCO2 are C# objects and both have Int32 Age property

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我不会写诗 2024-10-17 09:26:20

好吧,您可以创建自定义表达式访问者来替换参数引用和补丁成员访问表达式

class Converter<TTo>
{
    class ConversionVisitor : ExpressionVisitor
    {
        private readonly ParameterExpression newParameter;
        private readonly ParameterExpression oldParameter;

        public ConversionVisitor(ParameterExpression newParameter, ParameterExpression oldParameter)
        {
            this.newParameter = newParameter;
            this.oldParameter = oldParameter;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            return newParameter; // replace all old param references with new ones
        }

        protected override Expression VisitMember(MemberExpression node)
        {
            if (node.Expression != oldParameter) // if instance is not old parameter - do nothing
                return base.VisitMember(node);

            var newObj = Visit(node.Expression);
            var newMember = newParameter.Type.GetMember(node.Member.Name).First();
            return Expression.MakeMemberAccess(newObj, newMember);
        }
    }

    public static Expression<Func<TTo, TR>> Convert<TFrom, TR>(
        Expression<Func<TFrom, TR>> e
        )
    {
        var oldParameter = e.Parameters[0];
        var newParameter = Expression.Parameter(typeof(TTo), oldParameter.Name);
        var converter = new ConversionVisitor(newParameter, oldParameter);
        var newBody = converter.Visit(e.Body);
        return Expression.Lambda<Func<TTo, TR>>(newBody, newParameter);
    }
}

class A
{
    public int Value { get; set; }
}

class B
{
    public int Value { get; set; }
}

Expression<Func<A, int>> f = x => x.Value;
var f2 = Converter<B>.Convert(f);

well, you can make custom expression visitor that will replace parameter references and patch member access expressions

class Converter<TTo>
{
    class ConversionVisitor : ExpressionVisitor
    {
        private readonly ParameterExpression newParameter;
        private readonly ParameterExpression oldParameter;

        public ConversionVisitor(ParameterExpression newParameter, ParameterExpression oldParameter)
        {
            this.newParameter = newParameter;
            this.oldParameter = oldParameter;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            return newParameter; // replace all old param references with new ones
        }

        protected override Expression VisitMember(MemberExpression node)
        {
            if (node.Expression != oldParameter) // if instance is not old parameter - do nothing
                return base.VisitMember(node);

            var newObj = Visit(node.Expression);
            var newMember = newParameter.Type.GetMember(node.Member.Name).First();
            return Expression.MakeMemberAccess(newObj, newMember);
        }
    }

    public static Expression<Func<TTo, TR>> Convert<TFrom, TR>(
        Expression<Func<TFrom, TR>> e
        )
    {
        var oldParameter = e.Parameters[0];
        var newParameter = Expression.Parameter(typeof(TTo), oldParameter.Name);
        var converter = new ConversionVisitor(newParameter, oldParameter);
        var newBody = converter.Visit(e.Body);
        return Expression.Lambda<Func<TTo, TR>>(newBody, newParameter);
    }
}

class A
{
    public int Value { get; set; }
}

class B
{
    public int Value { get; set; }
}

Expression<Func<A, int>> f = x => x.Value;
var f2 = Converter<B>.Convert(f);
像你 2024-10-17 09:26:20

粗略步骤:


 Get the expression Cast it to BinaryExpression
 Get the left operand Cast it to MemberExpression
 Get the Underlying Type that the property belong to 
 Change it to your new type if you can.

正如我猜测的那样,您在这里获得的类型是一个没有 setter 的属性。

Expression<Func<MainWindow, bool >> exp1 = o => this.ActualHeight>50;
var type = ((MemberExpression)((BinaryExpression)exp1.Body).Left).Expression.Type;

所以你必须构建一个新的表达式

的方法

这是手动构建 x = 的 linq 表达式 > x.Child == itemToCompare.Child

Rough Steps:


 Get the expression Cast it to BinaryExpression
 Get the left operand Cast it to MemberExpression
 Get the Underlying Type that the property belong to 
 Change it to your new type if you can.

The type you get here is a property without setter as I guessed.

Expression<Func<MainWindow, bool >> exp1 = o => this.ActualHeight>50;
var type = ((MemberExpression)((BinaryExpression)exp1.Body).Left).Expression.Type;

So you must build a new expression

Here is the way

manually build linq expression for x => x.Child == itemToCompare.Child

烟燃烟灭 2024-10-17 09:26:20

理想情况下 - 你不会。创建一个描述 Age 属性的接口,并构建引用 that 的表达式。如果您无法修改 POCO 类型,请使用像 Go 这样的语言,其中接口是隐式的:-)。

Ideally - you don't. Make an interface that describes the Age property, and build the expression to refer to that. If you can't modify the POCO types, use a language like Go, where interfaces are implicit :-).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文