简体   繁体   English

C# 用于字符串插值的表达式树

[英]C# Expression tree for string interpolation

I have a program that reads a json file with some property names of a certain class.我有一个程序可以读取 json 文件,其中包含某个 class 的一些属性名称。 The values of the configured property names should compose up a key.配置的属性名称的值应该组成一个键。

Lets take an example:举个例子:

Class: Class:

class SomeClass
{
    public string PropertyOne { get; set; }
    public string PropertyTwo { get; set; }
    public string PropertyThree { get; set; }
    public string PropertyFour { get; set; }
}

var someClass = new SomeClass
            {
                PropertyOne = "Value1",
                PropertyTwo = "Value2",
                PropertyThree = "Value3",
                PropertyFour = "Value4",
            };

Configuration file:配置文件:

{
   "Properties": ["PropertyOne", "PropertyTwo"]
}

If I knew the properties at compile time I would have create a lambda like:如果我在编译时知道属性,我将创建一个 lambda ,例如:

Func<SomeClass, string> keyFactory = x => $"{x.PropertyOne}|{x.PropertoTwo}"

Is there a way to compile such a lambda using expressions?有没有办法使用表达式编译这样的 lambda ? Or any other suggestions maybe?或者任何其他建议?

In Expression Tree, string interpolation is converted to string.Format .在表达式树中,字符串插值被转换为string.Format Analogue of your sample will be:您的样品的类似物将是:

Func<SomeClass, string> keyFactory = 
   x => string.Format("{0}|{1}", x.PropertyOne, x.PropertoTwo);

The following function created such delegate dynamically:以下 function 动态创建了这样的委托:

private static MethodInfo _fromatMethodInfo = typeof(string).GetMethod(nameof(string.Format), new Type[] { typeof(string), typeof(object[]) });

public static Func<T, string> GenerateKeyFactory<T>(IEnumerable<string> propertyNames)
{
    var entityParam = Expression.Parameter(typeof(T), "e");

    var args = propertyNames.Select(p => (Expression)Expression.PropertyOrField(entityParam, p))
            .ToList();

    var formatStr = string.Join('|', args.Select((_, idx) => $"{{{idx}}}"));

    var argsParam = Expression.NewArrayInit(typeof(object), args);

    var body = Expression.Call(_fromatMethodInfo, Expression.Constant(formatStr), argsParam);
    var lambda = Expression.Lambda<Func<T, string>>(body, entityParam);
    var compiled = lambda.Compile();

    return compiled;
}

Usage:用法:

var keyFactory = GenerateKeyFactory<SomeClass>(new[] { "PropertyOne", "PropertyTwo", "PropertyThree" });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM