鉴于此课程
public class Foo
{
public string Name { get; set; }
}
这种方法(在其他一些类中)......
private Func<Foo, string> Compile(string body)
{
ParameterExpression prm = Expression.Parameter(typeof(Foo), "foo");
LambdaExpression exp = DynamicExpressionParser.ParseLambda(new[] { prm }, typeof(string), body);
return (Func<Foo, string>)exp.Compile();
}
将采用lambda表达式的右侧并给我一个委托。所以,如果这样调用:
Foo f = new Foo { Name = "Hamilton Academicals" };
//foo => foo.Name.Substring(0,3)
Func<Foo, string> fn = Compile("foo.Name.Substring(0,3)");
string sub = fn(f);
然后 sub 将具有值&#34; Ham&#34;。
一切都很好,但是,我想让Foo子类DynamicObject(这样我可以实现TryGetMember来动态计算属性值),所以我想采用表达式并得到相当于这个
Func<dynamic, dynamic> fn = foo => foo.Name.Substring(0,3);
我已尝试Expression.Dynamic
使用自定义CallSiteBinder
,但在Bar
类型中存在无属性或字段Object
时失败(当我尝试访问时)动态foo.Bar
。我假设这是因为需要动态调度get foo.Bar
的调用(使用Expression.Dynamic
),但这对我不起作用,因为关键目标是用户可以输入一个简单的表达式并执行它。有可能吗?
答案 0 :(得分:2)
我得到了这个,如果它能帮助你:
<强>编译器强>:
using System;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
namespace ConsoleApp4
{
public class Compiler
{
public static Func<CustomDynamic, TResult> Compile<TResult>(string body)
{
ParameterExpression prm = Expression.Parameter(typeof(CustomDynamic), typeof(CustomDynamic).Name);
LambdaExpression exp = DynamicExpressionParser.ParseLambda(new[] { prm }, typeof(TResult), body);
return (Func<CustomDynamic, TResult>)exp.Compile();
}
}
}
动态对象:
using System.Collections.Generic;
using System.Dynamic;
namespace ConsoleApp4
{
public class CustomDynamic
{
ExpandoObject _values;
public CustomDynamic()
{
_values = new ExpandoObject();
}
public void AddProperty(string propertyName, object propertyValue)
{
var expandoDict = _values as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
expandoDict[propertyName] = propertyValue;
else
expandoDict.Add(propertyName, propertyValue);
}
public string GetString(string propertyName)
{
var expandoDict = _values as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
return (string)expandoDict[propertyName];
else
throw new KeyNotFoundException($"dynamic object did not contain property {propertyName}");
}
public int GetInt(string propertyName)
{
var expandoDict = _values as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
return (int)expandoDict[propertyName];
else
throw new KeyNotFoundException($"dynamic object did not contain property {propertyName}");
}
}
}
使用案例
using System;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
CustomDynamic f = new CustomDynamic();
f.AddProperty("Name", "Hamiltonian Physics");
Func<CustomDynamic, string> fn = Compiler.Compile<string>("CustomDynamic.GetString(\"Name\").SubString(0, 3)");
string sub = fn(f);
Console.WriteLine(sub);
Console.ReadLine();
}
}
}
它只使用ExpandoObject
类。不幸的是,您需要通过其API来创建对象,例如&#34; AddProperty&#34;对于每一处房产,但是heyho。
对于通用方法,DynamicExpressionParser.ParseLambda
也有点痛苦,所以我必须创建特定于类型的访问器, 不是最好的,但是它正在工作。