[英]Need generic solution in reflection: create instance which may or may not have parameterless constructors
I am working on a project where I am sending commands to a device. 我正在一个项目中,我正在向设备发送命令。 Each command object has a one-to-one relationship to a specific command supported by the device (which are defined by the API of a supporting dll).
每个命令对象与设备支持的特定命令(由支持的dll的API定义)具有一对一的关系。
I have XML files which define the commands: name the method name, and parameters (by name, type, and default value). 我有定义命令的XML文件:命名方法名称和参数(按名称,类型和默认值)。
My application reads the XML and creates a command object. 我的应用程序读取XML并创建命令对象。 I have a parameter dictionary which has parameter names associated to values (by type).
我有一个参数字典,其中有与值关联的参数名称(按类型)。
When populating the parameter dictionary I started out creating a type, then an instance, then updating the dictionary. 当填充参数字典时,我开始创建类型,然后创建实例,然后更新字典。
{
theType = Type.GetType(paramType);
var newInstance = Activator.CreateInstance(theType, true);
parameterValueMap.Add(paramName, newInstance);
}
This works fine for ints, etc, but doesn't work for string types, as they don't have a parameterless constructor. 这对于int等有效,但对字符串类型无效,因为它们没有无参数构造函数。
As there may be other types with parameterless constructors, I need to keep the solution generic (not handle strings specifically). 由于可能有其他带有无参数构造函数的类型,因此我需要保持解决方案的通用性(而不是专门处理字符串)。
Can somebody help me with the solution? 有人可以为我提供解决方案吗? Is there a way to create an instance of a type with parameters without having an actual instance of the parameter (and instance of string in my specific case)?
有没有一种方法可以创建带有参数的类型的实例,而无需实际的参数实例(在我的特定情况下为字符串实例)?
Thanks -m 谢谢-m
Since you mention generics, a default(T)
may be useful, but that will be null
for classes / interfaces. 由于您提到了泛型,因此
default(T)
可能会有用,但是对于类/接口,该null
。 A handy evil trick is: 一个方便的邪恶技巧是:
T obj = (T)FormatterServices.GetUninitializedObject(typeof(T));
However! 然而! This is pure evil, usually reserved for deserialization / materialization libraries.
这是纯粹的恶魔,通常保留给反序列化/实体化库。 This is not intended for ad-hoc usage.
这不适合临时使用。
Perhaps the best approach is to let the caller tell you how, for example add an optional factory parameter: 也许最好的方法是让调用方告诉您如何进行操作,例如添加可选的工厂参数:
void YourMethod<T>(..., Func<T> constructor = null)
Then if they want the caller can supply a technique to create instances. 然后, 如果他们愿意 ,调用者可以提供一种创建实例的技术。 So you have:
所以你有了:
T obj = constructor == null ? (T)Activator.CreateInstance(typeof(T))
: constructor();
In any event: strings are a huge problem. 无论如何:字符串是一个很大的问题。 You will undoubtably need to special-case strings.
毫无疑问,您将需要特殊情况的字符串。
I use a Activator.CreateInstance(type, ParseKeys(ID).ToArray())
in my code, where ID
is a ||
我在代码中使用
Activator.CreateInstance(type, ParseKeys(ID).ToArray())
,其中ID
是||
separated list of key/value pairs, and ParseKeys()
is 键/值对的单独列表,并且
ParseKeys()
是
private static IEnumerable<object> ParseKeys(string keyString)
{
IEnumerable<string> keyStrings = keyString.Split(new string[] { "||" }, StringSplitOptions.RemoveEmptyEntries); // Use this construction to enable splitting on multiple characters
List<object> keys = new List<object>();
foreach (var key in keyStrings)
{
var type = Type.GetType(key.Split("|")[0]);
var value = key.Split("|")[1];
var data = Convert.ChangeType(value, type);
keys.Add(data);
}
return keys;
}
Obviously, you need to be able to represent your parameters as a string in some form, and I haven't tested it for parameterless constructors, but it works just fine for both ints and strings. 显然,您需要能够以某种形式将参数表示为字符串,并且我尚未针对无参数构造函数对其进行测试,但它对于int和字符串都适用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.