简体   繁体   English

需要反思的通用解决方案:创建可能具有或不具有无参数构造函数的实例

[英]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.

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