简体   繁体   English

C#动态类型初始化程序

[英]C# Dynamic Type Initializer

I'm trying to build something like the C# type initalizer dynamically: 我正在尝试动态构建类似C#type initalizer的东西:

MyClass class = new MyClass { MyStringProperty= inputString };

I want to build a generic method that reflects over a given type once and returns a delegate which creates a new instance of the class and populates it based on the input parameter. 我想构建一个泛型方法,它反映一次给定的类型并返回一个委托,该委托创建一个新的类实例并根据输入参数填充它。 The method signature might look like this: 方法签名可能如下所示:

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

And calling the resulting function would create a new instance of 'T' with (for example) every public property with of type String to the value of the input string argument. 并且调用结果函数将创建一个新的'T'实例,其中(例如)具有String类型的每个公共属性为输入字符串参数的值。

So assuming that 'MyClass' has only MyStringProperty, the code below would be functionally equivalent to the code at the beginning: 因此,假设'MyClass'只有MyStringProperty,下面的代码在功能上等同于开头的代码:

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

I'm pretty familiar with the System.Reflection and System.Linq.Expressions namespaces, and I've done some moderately complex things like this in the past, but this one has me stumped. 我对System.Reflection和System.Linq.Expressions命名空间非常熟悉,过去我做过一些像这样的中等复杂的事情,但这个让我很难过。 I want to build a compiled delegate, not simply iterate through the properties using reflection. 我想构建一个已编译的委托,而不是简单地使用反射遍历属性。

Thanks! 谢谢!

In CLR 4.0 you'll be able to build complete statements with Expressions. 在CLR 4.0中,您将能够使用表达式构建完整的语句。

Until then, you're looking at a code-gen job. 在那之前,你正在寻找一个代码生成工作。 The quickest way to prototype it would be by building C# in a StringBuilder and then calling the compiler on it. 原型化最快的方法是在StringBuilder中构建C#然后在其上调用编译器。 With caching it would perform okay. 通过缓存,它可以正常运行。

The hardcore way to do it would be to generate the IL and use Reflection Emit to build the method, thus avoiding calling out to the compiler. 这样做的核心方法是生成IL并使用Reflection Emit构建方法,从而避免调用编译器。

Uh, yeah so I was just making things way too complicated for myself. 呃,是的,所以我只是让事情变得太复杂了。 This is the method I was looking for: 这是我正在寻找的方法:

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;            
}

Unfortunately, I don't see this happening, although I'm no expert when it comes to the deep vodoo you can do with expressions and delegates. 不幸的是,我没有看到这种情况发生,虽然我不是专家,因为你可以用表达式和代表做深刻的vodoo。

The way I see it, you can only do this with reflection. 我看到它的方式,你只能通过反射来做到这一点。 Without reflection, you need to know at compile time what the names of each property you want to set are. 如果没有反射,您需要在编译时知道要设置的每个属性的名称。 You could do individual functions for each separate class you wanted to support, but that seems counter to the requirement of a generic, one-size-fits-all function. 您可以为要支持的每个单独的类执行单独的功能,但这似乎与通用的,一刀切的功能的要求相反。

May I ask why the function in the first place? 我可以问一下为什么功能在第一位? Some form of dependency injection? 某种形式的依赖注入?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM