需要在反射中使用通用解决方案:创建可能有也可能没有无参数构造函数的实例

时间:2012-09-27 18:22:02

标签: c# reflection

我正在开发一个项目,我将命令发送到设备。每个命令对象与设备支持的特定命令(由支持dll的API定义)具有一对一的关系。

我有定义命令的XML文件:命名方法名称和参数(按名称,类型和默认值)。

我的应用程序读取XML并创建一个命令对象。我有一个参数字典,其参数名称与值相关联(按类型)。

填充参数字典时,我开始创建一个类型,然后是一个实例,然后更新字典。

{
    theType = Type.GetType(paramType);
    var newInstance = Activator.CreateInstance(theType, true);
    parameterValueMap.Add(paramName, newInstance);
}

这适用于整数等,但不适用于字符串类型,因为它们没有无参数构造函数。

由于可能有其他类型的无参数构造函数,我需要保持解决方案的通用性(不专门处理字符串)。

有人可以帮我解决这个问题吗?有没有办法用参数创建一个类型的实例,而没有参数的实际实例(以及我特定情况下的字符串实例)?

由于 -m

2 个答案:

答案 0 :(得分:1)

由于您提到了泛型,default(T)可能很有用,但对于类/接口,它将是null。一个方便的邪恶技巧是:

T obj = (T)FormatterServices.GetUninitializedObject(typeof(T));

然而!这是纯粹的邪恶,通常保留用于反序列化/实现库。这不适用于临时使用。

也许最好的方法是让调用者告诉你如何添加一个可选的工厂参数:

 void YourMethod<T>(..., Func<T> constructor = null)

然后如果他们想要,调用者可以提供创建实例的技术。所以你有:

T obj = constructor == null ? (T)Activator.CreateInstance(typeof(T))
                            : constructor();

无论如何:字符串是一个很大的问题。毫无疑问,您需要使用特殊字符串。

答案 1 :(得分:0)

我在代码中使用Activator.CreateInstance(type, ParseKeys(ID).ToArray()),其中ID||分隔的键/值对列表,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;
    }

显然,你需要能够以某种形式将你的参数表示为一个字符串,而我没有为无参数构造函数测试它,但它对于整数和字符串都可以正常工作。