Dr *_*izo 3 c# generics reflection expression-trees
我正在努力解决一些问题.我最初创建了一个通用层,它位于我的业务对象和工作正常的数据访问层之间.然后,我最近阅读了一些名为Expression Trees的内容,它显然更有效,并且已经证明是这样,因为我将Activator.CreateInstance()与表达式交换,并以指数方式改进了我的通用层.
我还在阅读有关整个区域(表达式)的一些内容,但我遇到了一些我想尝试制作通用的代码.目前,你必须传递一个具体的类型,如字符串,int,十进制等.我有点通用.我试了几件但失败了.我想要通用的位是Action,我不想传入一个字符串,我希望能够传递一般属性的类型,即typeof(T).GetProperty("Forename").PropertyType.这可能吗?正在考虑做一个有点foo bar的switch语句.
在此先感谢Onam.
public class TTT<T> where T : new()
{
public void Do(object t)
{
MethodInfo info = typeof(T).GetProperty("Forename").GetSetMethod();
ParameterExpression param = Expression.Parameter(typeof(string), "val");
MethodCallExpression call = Expression.Call(Expression.Constant(t), info,
new ParameterExpression[] { param });
Action<string> action = Expression.Lambda<Action<string>>(call, param).Compile();
action("hi");
}
}
Run Code Online (Sandbox Code Playgroud)
首先,请注意,这不是一个好方法; 如果您正在构建Expression每次调用,然后执行Compile()它,然后调用它,则没有性能优势.反思会更快.如果您需要性能,请查看诸如"FastMember"之类的库,其中只有以下内容:
var accessor = TypeAccessor.Create(typeof(T));
accessor[target, "Forename"] = value;
Run Code Online (Sandbox Code Playgroud)
(通过元编程和自动缓存完全优化的地方)
如果您希望类型是动态的,那么有两个选项:
Expression.GetActionType和使用DynamicInvoke- 非常糟糕的性能(提示:不要这样做)Action<object>并在表达式内执行强制转换(精细)所以类似于:
using System;
using System.Linq.Expressions;
using System.Reflection;
class Foo
{
public string Forename {get;set;}
}
class Test<T>
{
public void Do(object target, object value)
{
var obj = Expression.Constant(target, typeof(T));
var member = Expression.PropertyOrField(obj, "Forename");
var param = Expression.Parameter(typeof(object));
Type type;
switch(member.Member.MemberType)
{
case MemberTypes.Field:
type = ((FieldInfo)member.Member).FieldType; break;
case MemberTypes.Property:
type = ((PropertyInfo)member.Member).PropertyType; break;
default:
throw new NotSupportedException(member.Member.MemberType.ToString());
}
var body = Expression.Assign(member, Expression.Convert(param, type));
var lambda = Expression.Lambda<Action<object>>(body, param);
lambda.Compile()(value);
}
}
static class Program
{
static void Main()
{
var obj = new Foo();
new Test<Foo>().Do(obj, "abc");
Console.WriteLine(obj.Forename);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3080 次 |
| 最近记录: |