亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在表達式中使用 ExpandoObject 代替原始實體

在表達式中使用 ExpandoObject 代替原始實體

C#
湖上湖 2023-09-24 16:20:30
我有這樣的表達:Expression<Func<MyEntity, bool>> exp = x => x.FirstName == "Jonas";該表達式被傳輸到另一個不具有類型的應用程序MyEntity。為了能夠執行表達式,我嘗試將其中的類型替換為ExpandoObject使用ExpressionVistor. public class ReplaceToExpandoVisitor : ExpressionVisitor    {        ParameterExpression _parameter;        private Type _targetType = typeof(ExpandoObject);        public ReplaceToExpandoVisitor(ParameterExpression p2)        {            _parameter = p2;        }        protected override Expression VisitParameter(ParameterExpression node)        {            return _parameter;        }        protected override Expression VisitMember(MemberExpression node)        {            if (node.Member.MemberType != System.Reflection.MemberTypes.Property)                throw new NotSupportedException();            var memberName = node.Member.Name;            var propBinder = Binder.GetMember(CSharpBinderFlags.None,                memberName,                 GetType(),                 new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });            var inner = Visit(node.Expression);            // this is the right way, right?            var exp2 = Expression.Dynamic(propBinder, typeof(object), inner);            // I need to convert it right? Otherwise it will be of type object?            var propGetExpression = Expression.Convert(exp2, node.Type);            return propGetExpression;        }    }然而,該表達式在執行時返回 false。所以我想我沒有正確訪問 Expandoobject 中的“屬性”。有人可以解釋我做錯了什么嗎?
查看完整描述

1 回答

?
翻閱古今

TA貢獻1780條經驗 獲得超5個贊

我認為你使用活頁夾使事情變得過于復雜。ExpandoObject實現IDictionary<string, object>接口,因此您可以替換x => x.FirstName == "Jonas"為x => x["FirstName"] == "Jonas"哪個應該更容易。另外,您必須重寫VisitLambda, 來修改類型參數,否則轉換將失敗。


這是示例代碼:


public class ReplaceToExpandoVisitor<TSource> : ExpressionVisitor

{

    private static readonly PropertyInfo ItemProperty = typeof(IDictionary<string, object>).GetProperty("Item");


    private readonly ParameterExpression _targetParameter = Expression.Parameter(typeof(ExpandoObject));


    protected override Expression VisitLambda<T>(Expression<T> node)

    {

        var body = this.Visit(node.Body);

        var parameters = node.Parameters.Select(this.Visit).Cast<ParameterExpression>();


        return Expression.Lambda(body, parameters);

    }


    protected override Expression VisitParameter(ParameterExpression node)

    {

        if (node.Type == typeof(TSource))

        {

            return this._targetParameter;

        }


        return node;

    }


    protected override Expression VisitMember(MemberExpression node)

    {

        if (node.Member.MemberType != MemberTypes.Property)

        {

            throw new NotSupportedException();

        }


        string memberName = node.Member.Name;


        return Expression.Convert(

            Expression.Property(

                this.Visit(node.Expression),

                ItemProperty, 

                Expression.Constant(memberName)

            ), 

            ((PropertyInfo)node.Member).PropertyType

        );

    }

}

用法:


Expression<Func<MyEntity, bool>> exp = x => x.FirstName == "Jonas";

Expression<Func<ExpandoObject, bool>> exp2 = (Expression<Func<ExpandoObject, bool>>) new ReplaceToExpandoVisitor<MyEntity>().Visit(exp);


dynamic obj = new ExpandoObject();

obj.FirstName = "Jonas";


bool result = exp2.Compile().Invoke(obj);


查看完整回答
反對 回復 2023-09-24
  • 1 回答
  • 0 關注
  • 164 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號