假设我有以下代码更新struct
使用反射的字段.由于struct实例被复制到DynamicUpdate
方法中,因此需要在传递之前将其装箱到对象.
struct Person
{
public int id;
}
class Test
{
static void Main()
{
object person = RuntimeHelpers.GetObjectValue(new Person());
DynamicUpdate(person);
Console.WriteLine(((Person)person).id); // print 10
}
private static void DynamicUpdate(object o)
{
FieldInfo field = typeof(Person).GetField("id");
field.SetValue(o, 10);
}
}
Run Code Online (Sandbox Code Playgroud)
代码工作正常.现在,假设我不想使用反射,因为它很慢.相反,我想生成一些CIL直接修改id
字段并将该CIL转换为可重用的委托(例如,使用动态方法功能).特别是,我想用s/t替换上面的代码,如下所示:
static void Main()
{
var action = CreateSetIdDelegate(typeof(Person));
object person = RuntimeHelpers.GetObjectValue(new Person());
action(person, 10);
Console.WriteLine(((Person)person).id); // print 10
}
private static Action<object, object> CreateSetIdDelegate(Type t)
{
// build dynamic method …
Run Code Online (Sandbox Code Playgroud) 我是表达式的新手,我想知道如何以任何方式转换我的表达式
让我们说在这个例子中我的TModel是Customer类型,并将它分配给这样的地方:
Expression<Func<TModel, string>> getvalueexpression = customer =>customer.Name
Run Code Online (Sandbox Code Playgroud)
喜欢的东西
Expression<Action<TModel,string>> setvalueexpression = [PSEUDOCODE] getvalueexpression = input
Action<TModel,string> Setter = setvalueexpression.Compile();
Setter(mycustomer,value);
Run Code Online (Sandbox Code Playgroud)
所以简而言之,我想以某种方式构建和编译一个表达式,该表达式将我的getter表达式指定的客户名称设置为特定值.
继例子这篇文章和它的后续问题,我试图创建一个使用编译表达式场getter/setter方法.
getter工作得很好,但是我被困在了setter中,因为我需要setter来分配任何类型的字段.
在这里我的setter-action builder:
public static Action<T1, T2> GetFieldSetter<T1, T2>(this FieldInfo fieldInfo) {
if (typeof(T1) != fieldInfo.DeclaringType && !typeof(T1).IsSubclassOf(fieldInfo.DeclaringType)) {
throw new ArgumentException();
}
ParameterExpression targetExp = Expression.Parameter(typeof(T1), "target");
ParameterExpression valueExp = Expression.Parameter(typeof(T2), "value");
//
// Expression.Property can be used here as well
MemberExpression fieldExp = Expression.Field(targetExp, fieldInfo);
BinaryExpression assignExp = Expression.Assign(fieldExp, valueExp);
//
return Expression.Lambda<Action<T1, T2>> (assignExp, targetExp, valueExp).Compile();
}
Run Code Online (Sandbox Code Playgroud)
现在,我将通用setter存储到缓存列表中(当然,每次构建setter都是性能杀手),我将它们转换为简单的"对象":
// initialization of the setters dictionary
Dictionary<string, object> setters = new Dictionary(string, object)();
Dictionary<string, …
Run Code Online (Sandbox Code Playgroud) 我想定义一些lambda表达式来表示类实例属性的更新。
我试着写如下:
Expression<Action<User>> update = user => user.Name = "Joe Foo";
Run Code Online (Sandbox Code Playgroud)
但是我有一个编译错误:
错误CS0832表达式树可能不包含赋值运算符。
如何用lambda表示此更新。
编辑
我的目标是使业务服务将更新发送到通用存储库。该存储库可以分析lambda的表达式以构建查询以发送到数据库引擎。
商业服务的示例可以是:
Expression<Action<User>> update = user => user.Name = "Joe Foo";
Run Code Online (Sandbox Code Playgroud)