C#动态类型初始化

问题描述:

我试图建立类似动态的C#类型initalizer:C#动态类型初始化

MyClass class = new MyClass { MyStringProperty= inputString }; 

我想建立一个反映在给定类型而返回它创建了一个新的委托泛型方法类的实例并根据输入参数填充它。该方法的签名可能是这样的:

Func<string,T> CreateFunc<T>(); 

并调用结果函数将创建“T”的新实例(例如)每辆公共属性类型为String的到输入字符串参数的值。

所以假设“MyClass的”只有MyStringProperty,下面的代码会在一开始的功能等效于代码:

var func = CreateFunc<MyClass>(); 
func.Invoke(inputString); 

我很熟悉的System.Reflection和System.Linq的。表达式名称空间,过去我做了一些中等复杂的事情,但是这个让我很难过。我想要构建一个编译的委托,而不是简单地使用反射遍历属性。

谢谢!

呃,是的,所以我只是让自己变得太复杂了。这是我正在寻找的方法:

public static Func<string, T> CreateFunc<T>() 
    where T : class 
{ 
    var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); 
    var param = Expression.Parameter(typeof(string),"o"); 
    var constructorInfo = typeof(T).GetConstructor(new Type[] { }); 
    List<MemberBinding> bindings = new List<MemberBinding>(); 
    foreach (var property in properties) 
     bindings.Add(Expression.Bind(property, param)); 

    var memberInit = Expression.MemberInit(Expression.New(constructorInfo), bindings); 

    var func = Expression.Lambda<Func<string, T>>(memberInit, new ParameterExpression[] {param}).Compile(); 

    return func;    
} 
+0

看起来你还在使用反射,你只是(本质上)缓存反射的结果。 – Randolpho 2010-02-19 21:16:29

+0

很酷,我忘了有关于属性初始化的表达式节点类型,并且假定需要几个单独的语句。@Randolpho,是的,这就是我在对你的回答的评论中试图解释的。 – 2010-02-19 22:49:29

+0

是的,我没有意识到初始化器存在,只是假设我必须自己创建。当我写这个问题时,这比我想象的要简单。 – Paul 2010-02-20 01:06:22

在CLR 4.0中,您将能够使用表达式构建完整的语句。

在此之前,你正在寻找一个代码工作。最简单的原型方法是在StringBuilder中构建C#,然后调用编译器。随着缓存它会表现良好。

这样做的核心方法是生成IL并使用Reflection Emit来构建方法,从而避免调用编译器。

不幸的是,我没有看到发生这种情况,虽然我不是专家,但对于表达式和代表可以做深层次的vodoo。

我看到它的方式,你只能用反射来做到这一点。没有反思,你需要在编译时知道你想设置的每个属性的名称是什么。你可以为你想要支持的每个单独的类做单独的功能,但这似乎与通用的,一刀切的功能的要求相反。

请问为什么功能在第一位?某种形式的依赖注入?

+0

不,这当然是可以的。反射发出(或者在运行时生成的C#源代码的字符串上调用编译器)使您可以在运行时以小的延迟突发有效地继续编译过程。您使用反射来获取信息,并从中构建代码,并缓存生成的委托,以便您不必再次执行反射。 – 2010-02-19 19:34:41

+0

之所以这样,是因为我必须部署一个程序集,以后我将无法进行更改,但我不想在当前类型上创建很大的依赖关系。我很确定我只是想出了它,我会发布我想出来的任何东西。 – Paul 2010-02-19 19:36:05