表达式树使用类的属性值创建字典

Expression tree create dictionary with property values for class(表达式树使用类的属性值创建字典)
本文介绍了表达式树使用类的属性值创建字典的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我尝试使用表达式树来完成此操作

var properties = new Dictionary<string, object>();

foreach (var propInfo in objType.GetTypeInfo().GetProperties(BindingFlags.Public))
{
    var name = propInfo.Name;
    var value = propInfo.GetValue(objInstance);

    properties.Add(name, value);
}

return properties;

即创建名称和值对的字典,其中name是objType的属性名称,value是objType的实例objInstance的属性值

现在将其转换为表达式应编译为仅执行以下操作的委托

Func<T, Dictionary<string, object>> func = i =>
{
    var properties = new Dictionary<string, object>();

    properties.Add("Prop1", (object)i.Prop1);
    properties.Add("Prop2", (object)i.Prop2);
    properties.Add("Prop3", (object)i.Prop3);
    // depending upon the number of properties of T, Add will continue

    return properties;
};

我知道如何执行其中的一些操作,但我不确定的是如何创建字典的本地实例,然后在后续表达式中使用它(并返回它)?

推荐答案

应该类似于(内联注释):

public static Func<T, Dictionary<string, object>> GetValuesFunc<T>()
{
    Type objType = typeof(T);

    var dict = Expression.Variable(typeof(Dictionary<string, object>));
    var par = Expression.Parameter(typeof(T), "obj");

    var add = typeof(Dictionary<string, object>).GetMethod("Add", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(string), typeof(object) }, null);

    var body = new List<Expression>();
    body.Add(Expression.Assign(dict, Expression.New(typeof(Dictionary<string, object>))));

    var properties = objType.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance);

    for (int i = 0; i < properties.Length; i++)
    {
        // Skip write only or indexers
        if (!properties[i].CanRead || properties[i].GetIndexParameters().Length != 0)
        {
            continue;
        }

        var key = Expression.Constant(properties[i].Name);
        var value = Expression.Property(par, properties[i]);
        // Boxing must be done manually... For reference type it isn't a problem casting to object
        var valueAsObject = Expression.Convert(value, typeof(object));
        body.Add(Expression.Call(dict, add, key, valueAsObject));
    }

    // Return value
    body.Add(dict);

    var block = Expression.Block(new[] { dict }, body);

    var lambda = Expression.Lambda<Func<T, Dictionary<string, object>>>(block, par);
    return lambda.Compile();
}

使用方法如下:

public class Test
{
    public int A { get; set; }
    public string B { get; set; }
}

Func<Test, Dictionary<string, object>> fn = GetValuesFunc<Test>();

var obj = new Test
{
    A = 5,
    B = "Foo"
};

var res = fn(obj);

这篇关于表达式树使用类的属性值创建字典的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)