I was just going through some articles on reflection and generics, and I came across the following code:
我刚刚阅读了一些关于反射和泛型的文章,我遇到了以下代码:
public static T CreateControlInstance<T>(FormControl parent)
where T : FormControl
{
T control = GetControlInstance<T>(parent);
//do something with control
}
public static T GetControlInstance<T>(FormControl parent)
{
return (T)Activator.CreateInstance(typeof(T), new object[] { parent });
}
These methods were used like this:
这些方法使用如下:
MyButton b = CreateControlInstance<MyButton>(SomeformInstance);
Many controls were created this way. I would just like to know:
许多控件都是这样创建的。我只想知道:
Q1. What are the advantages of this approach?
Q1。这种方法有哪些优点?
Q2. What are the advantages of this approach, given that the object instance types are known at compile time? (I'm assuming that the button and FormControl
were somehow related to System.Windows.Forms.Control
)
Q2。鉴于对象实例类型在编译时是已知的,这种方法的优点是什么? (我假设按钮和FormControl以某种方式与System.Windows.Forms.Control相关)
Edit:
I found something similar being done here Create instance of generic type?
编辑:我在这里发现了类似的东西创建泛型类型的实例?
Basically i want to create type(of known type) from strings which got read at runtime?
I wanted to avoid long list of if-then-else in creating objects of specific type depending on the string..but didn't have a clue.
Any one has better solution so that reflection can be avoided to create elements of known type.
End Edit
基本上我想从运行时读取的字符串创建类型(已知类型)?我想避免使用if-then-else的长列表来创建特定类型的对象,具体取决于字符串...但是没有线索。任何人都有更好的解决方案,以便可以避免反射来创建已知类型的元素。结束编辑
3 个解决方案
#1
3
The problem with generics is that you can't define a constraint on a complex constructor. The only constraint is the availability of an empty constructor.
泛型的问题是您无法在复杂的构造函数上定义约束。唯一的限制是空构造函数的可用性。
public static T CreateInstance<T>() where T : new()
{
return new T();
}
However, when you want to pass parameter, you'll have to use other methods, such as Activator.CreateInstance
. You can also use lambda.
但是,当您想要传递参数时,您将不得不使用其他方法,例如Activator.CreateInstance。你也可以使用lambda。
public static T CreateInstance<T>(Func<FormControl, T> builder, FormControl parent)
{
return builder(parent);
}
But you'll have to provide a specific lambda for constructing your object, for each different object.
但是你必须为每个不同的对象提供一个特定的lambda来构造你的对象。
MyButton b = CreateInstance<MyButton>(parent => new MyButton(parent), SomeformInstance);
By using reflection, you can make code simpler and automatically use a pre-defined constructor. But by using lambda, you can use class that don't match a given convention and fill other constructor arguments with you own data.
通过使用反射,您可以使代码更简单并自动使用预定义的构造函数。但是通过使用lambda,您可以使用与给定约定不匹配的类,并使用您自己的数据填充其他构造函数参数。
var b2 = CreateInstance<MyOtherButton>(
parent => new MyOtherButton("name", 42, parent), SomeformInstance
);
#2
2
If you are going to create a lot of controls this way, you'll notice that your app will be running slow. This is because Activator.CreateInstance is 10000 times slower than simple new(). Do keep that in mind.
如果您打算以这种方式创建大量控件,您会注意到您的应用程序运行缓慢。这是因为Activator.CreateInstance比简单的new()慢10000倍。请记住这一点。
#3
0
The only advantage is that you can perform extra processing.
唯一的优点是您可以执行额外的处理。
You could e.g. expand the CreateControlInstance<T>
method with some extra processing which needs to be performed for ever control.
你可以,例如扩展CreateControlInstance
However, when the choice is between
但是,当选择之间
MyButton b = CreateControlInstance<MyButton>(SomeformInstance);
and
和
MyButton b = new MyButton(SomeformInstance);
There is absolutely no reason to not choose the latter. The former will perform worse and will clutter your code unnecessarily.
绝对没有理由不选择后者。前者会表现更差,并且会不必要地混乱您的代码。
#1
3
The problem with generics is that you can't define a constraint on a complex constructor. The only constraint is the availability of an empty constructor.
泛型的问题是您无法在复杂的构造函数上定义约束。唯一的限制是空构造函数的可用性。
public static T CreateInstance<T>() where T : new()
{
return new T();
}
However, when you want to pass parameter, you'll have to use other methods, such as Activator.CreateInstance
. You can also use lambda.
但是,当您想要传递参数时,您将不得不使用其他方法,例如Activator.CreateInstance。你也可以使用lambda。
public static T CreateInstance<T>(Func<FormControl, T> builder, FormControl parent)
{
return builder(parent);
}
But you'll have to provide a specific lambda for constructing your object, for each different object.
但是你必须为每个不同的对象提供一个特定的lambda来构造你的对象。
MyButton b = CreateInstance<MyButton>(parent => new MyButton(parent), SomeformInstance);
By using reflection, you can make code simpler and automatically use a pre-defined constructor. But by using lambda, you can use class that don't match a given convention and fill other constructor arguments with you own data.
通过使用反射,您可以使代码更简单并自动使用预定义的构造函数。但是通过使用lambda,您可以使用与给定约定不匹配的类,并使用您自己的数据填充其他构造函数参数。
var b2 = CreateInstance<MyOtherButton>(
parent => new MyOtherButton("name", 42, parent), SomeformInstance
);
#2
2
If you are going to create a lot of controls this way, you'll notice that your app will be running slow. This is because Activator.CreateInstance is 10000 times slower than simple new(). Do keep that in mind.
如果您打算以这种方式创建大量控件,您会注意到您的应用程序运行缓慢。这是因为Activator.CreateInstance比简单的new()慢10000倍。请记住这一点。
#3
0
The only advantage is that you can perform extra processing.
唯一的优点是您可以执行额外的处理。
You could e.g. expand the CreateControlInstance<T>
method with some extra processing which needs to be performed for ever control.
你可以,例如扩展CreateControlInstance
However, when the choice is between
但是,当选择之间
MyButton b = CreateControlInstance<MyButton>(SomeformInstance);
and
和
MyButton b = new MyButton(SomeformInstance);
There is absolutely no reason to not choose the latter. The former will perform worse and will clutter your code unnecessarily.
绝对没有理由不选择后者。前者会表现更差,并且会不必要地混乱您的代码。