我想将以下字符串转换为函数委托(delegate)。
[Id]-[Description]
C# 类:
public class Foo
{
public string Id {get;set;}
public string Description {get;set;}
}
结果函数委托(delegate):
Func<Foo, string> GetExpression = delegate()
{
return x => string.Format("{0}-{1}", x.Id, x.Description);
};
我认为编译的 lambda 或表达式解析器是这里的一种方式,但不确定最好的方式。有什么意见吗?
最佳答案
可能是:构建 Linq 表达式然后编译它。编译表达式是一个普通的委托(delegate),没有性能缺陷。
如果参数类型 (Foo
) 在编译时已知的实现示例:
class ParserCompiler
{
private static (string format, IReadOnlyCollection<string> propertyNames) Parse(string text)
{
var regex = new Regex(@"(.*?)\[(.+?)\](.*)");
var formatTemplate = new StringBuilder();
var propertyNames = new List<string>();
var restOfText = text;
Match match;
while ((match = regex.Match(restOfText)).Success)
{
formatTemplate.Append(match.Groups[1].Value);
formatTemplate.Append("{");
formatTemplate.Append(propertyNames.Count);
formatTemplate.Append("}");
propertyNames.Add(match.Groups[2].Value);
restOfText = match.Groups[3].Value;
}
formatTemplate.Append(restOfText);
return (formatTemplate.ToString(), propertyNames);
}
public static Func<T, string> GetExpression<T>(string text) //"[Id]-[Description]"
{
var parsed = Parse(text); //"{0}-{1} Id, Description"
var argumentExpression = Expression.Parameter(typeof(T));
var properties = typeof(T)
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField)
.ToDictionary(keySelector: propInfo => propInfo.Name);
var formatParamsArrayExpr = Expression.NewArrayInit(
typeof(object),
parsed.propertyNames.Select(propName => Expression.Property(argumentExpression, properties[propName])));
var formatStaticMethod = typeof(string).GetMethod("Format", BindingFlags.Static | BindingFlags.Public, null,new[] { typeof(string), typeof(object[]) }, null);
var formatExpr = Expression.Call(
formatStaticMethod,
Expression.Constant(parsed.format, typeof(string)),
formatParamsArrayExpr);
var resultExpr = Expression.Lambda<Func<T, string>>(
formatExpr,
argumentExpression); // Expression<Func<Foo, string>> a = (Foo x) => string.Format("{0}-{1}", x.Id, x.Description);
return resultExpr.Compile();
}
}
和用法:
var func = ParserCompiler.GetExpression<Foo>("[Id]-[Description]");
var formattedString = func(new Foo {Id = "id1", Description = "desc1"});
关于c# - 字符串表达式到 c# 函数委托(delegate),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56184406/