动态生成属性和空参数的表达式 [英] Dynamically generate expression of property and empty argument

查看:53
本文介绍了动态生成属性和空参数的表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:请注意,这并非重复.

Note: please pay attention carefully this is not a duplicate.

我需要创建以下Lambda表达式:

I need to create the following Lambda expression:

() => model.property

模型及其属性将在运行时确定.我想要一个具有模型和属性并生成表达式的函数:

the model and its property will be determine at runtime. I want a function that takes the model and property and generate the expression:

public object GenerateLambda(object model, string property) 
{

}

如果可能,我不希望该函数是通用的. 但我认为我遇到的主要问题是()表达式.

If it is possible I don't want the function to be generic. but I think the main problem that I have is with () expression.

更新:现在,GenerateLambda的返回类型对我来说并不重要.可以替换而不是()=>model.property的任何结果都将被接受.我使用object的原因是我不知道属性的泛型类型,并且它们应该是动态的,但是当我测试时,可以将对象强制转换为Expression<Func<TValue?>>,这是我需要的最终类型(是属性类型,但将在运行时确定.)

Update : The return type of GenerateLambda is not important for me right now. Any result that could be replaced instead of ()=>model.property is accepted. The reason that I used object is that I don't know the generic types of properties and they should be dynamic, but as I tested it is possible to cast object to Expression<Func<TValue?>> which is the the final type that I need(TValue is the property type but it will be determined at runtime).

我创建了一系列Blazor组件,这些组件具有类型为Expression<Func<TValue?>>的属性(即For),该属性用于提取模型的自定义属性.我使用此属性的方式是通过以下方式将其设置为Func:() => person.FirstName.现在,我需要为对象(模型)的每个属性动态生成此表达式.假设该对象及其类型本身不是动态创建的.

I have created a series of Blazor components that have a property(namely For) of type Expression<Func<TValue?>> which is used to extract custom attribute of models. The way I use this property is by setting it to a Func in this way : () => person.FirstName. Now I need to generate this expression dynamically for each property of the object(model). Suppose that the object and its type themselves are not dynamically created created.

因此,对于模型中的每个属性p我都想调用GenerateLambda(object model, string property),它应该返回() => model.p.

So for each property p in model I want to call GenerateLambda(object model, string property) that should return () => model.p.

伪代码:

foreach(propertyInfo p in model){
   var result= GenerateLambda(model, p, X or any parameter that is needed);
   MyComponent.For= result;
    ... // other logics
}

推荐答案

类似以下内容:

public static IEnumerable<Func<object>> GetGetters(object obj)
{
    var type = obj.GetType();

    var obj2 = Expression.Constant(obj);

    foreach (var prop in type.GetProperties())
    {
        Expression prop2 = Expression.Property(obj2, prop);

        // The boxing for value type is explicit, 
        // downcasting to reference type is implicit
        if (prop2.Type.IsValueType)
        {
            prop2 = Expression.Convert(prop2, typeof(object));
        }

        var lambda = Expression.Lambda<Func<object>>(prop2);
        var compiled = lambda.Compile();
        yield return compiled;
    }
}

像这样使用:

var model = new
{
    Prop1 = 1,
    Prop2 = new[] { 1, 2, 3 },
    Prop3 = "Hello"
};

var test = GetGetters(model).ToArray();

这是代码的v1版本.更好的版本会在obj周围创建闭包并缓存表达式树...不确定是否确实可能.嗯,不……用表达式树来招惹似乎是不可能的.对于表达式树,创建一个返回另一个方法的方法是不可以的.您需要反射发射.

This is a v1 of the code... A better version would create closures around the obj and cache the expression trees... Not sure if it is really possibible. Mmmh no... currying with Expression trees doesn't seem to be possible. Creating a method that returns another method is a big no no with Expression trees. You need Reflection emit.

需要明确的是,最佳的选择是能够生成以下内容:

To be clear, the optimum would be to be able to generate this:

public static Func<object>[] MakeGetterProp1(MyClass obj)
{
    Func<object> fn1 = () => obj.Prop1;
    Func<object> fn2 = () => obj.Prop2;
    return new[] { fn1, fn2 };
}

通过使用表达式树.该方法将在第一次构建并缓存.然后,您可以调用它并收到一组Fun<object>"closed"(关闭)消息.围绕特定的obj.我不可能说.

through the use of an expression tree. This method would be built the first time and cached. Then you could call it and receive a set of Fun<object> "closed" around a particular obj. Not possible I would say.

这篇关于动态生成属性和空参数的表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆