【问题标题】:How to generate an instance of an unknown type at runtime?如何在运行时生成未知类型的实例?
【发布时间】:2010-12-15 21:38:32
【问题描述】:

我在 C# 中有以下内容:

string typename = "System.Int32";
string value = "4";

这两个字符串应该被用来生成具有指定值的指定类型的对象...

结果应该是:

object o = CreateUnknownType(typename, value);
...
Int32 test = (Int32)o;

【问题讨论】:

  • 你的问题是?如果稍后要将其转换为已知类型,为什么还要尝试创建未知类型?
  • 问题是:如何在运行时生成一个未知类型的实例?不管为什么或为什么不重要,我只是想知道它是否可能
  • 那很容易,是的,这是可能的。可行吗?可能不是。当您的示例没有意义时,询问一些上下文是否不合理?

标签: c# .net types runtime


【解决方案1】:

使用后:

Type type = Type.GetType(typename);

试试这个扩展方法:

public static class ReflectionExtensions
{
    public static T CreateInstance<T>(this Type source, params object[] objects)
        where T : class
    {            
        var cons = source.GetConstructor(objects.Select(x => x.GetType()).ToArray());
        return cons == null ? null : (T)cons.Invoke(objects);
    }
}

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    这是一个涉及 Azure SQL 联合的问题的具体示例...它根据键范围将数据拆分为单独的数据库。

    键范围类型有:

    SQL / .Net SQL 类型 / CLR.Net

    INT / SqlInt32 / Int32,可空

    BIGINT / SqlInt64 / Int64,可空

    UNIQUEIDENTIFIER / SqlGuid /Guid,可空

    VARBINARY(n),最大 n 900 / SqlBytes,SqlBinary /Byte[]

    理想情况下,C# 函数参数可以采用 .Net SQL 类型或 CLR .Net 类型,但只选择一种类型就可以了。

    “对象”类型参数会是要走的路吗?而且,是否有一种可行的方法来识别类型并进行相应的转换?

    这个概念类似于:

    public void fn(object obj, string fedName, string distName, bool filteringOn)

    {

    ...弄清楚 obj 是什么类型,以确保它是可接受的类型之一...

    字符串键 = obj.toString();

    return string.Format("USE FEDERATION {0} ({1}='{2}') WITH RESET, FILTERING = {3}", fedName, distName, key, (filteringOn ? "ON" : "OFF "));

    }

    虽然参数值被转换为字符串,但它将在 sql server 端重新转换/检查,因此需要在应用端进行验证。

    【讨论】:

      【解决方案3】:

      也许你有一组不同的类型,它们都实现了一个已知的接口?

      例如,如果您有多个不同的用户控件并希望将其中一个加载到容器中,则每个控件都可能实现 IMyWobblyControl(一个已知接口),但您可能直到运行时才知道要加载其中的哪个,可能来自读取字符串来自某种形式的配置文件。

      在这种情况下,您需要使用反射从诸如完整程序集名称之类的内容中加载实际类型,然后将其转换为您已知的类型以使用它。

      当然,您需要确保您的代码能够处理无效的强制转换、未找到程序集以及任何其他可能出现的异常情况...

      【讨论】:

        【解决方案4】:

        创建一个你知道名字的类型的实例(并且应该有一个默认的构造函数):

           string typeName = "System.Int32";
           Type type = Type.GetType(type);
           object o = Activator.CreateInstance(type);
        

        从字符串中解析一个值显然只适用于有限的一组类型。你可以

        • 按照建议使用Convert.ChangeType 作者 PhilipW
        • 或者创建一个 Dictionary&lt;Type,Func&lt;string,object&gt;&gt; 将已知类型映射到已知解析 功能
        • 或使用反射来调用 类型上的 Parse(string) 方法, 假设有一个:

             string valueText = "4";
             MethodInfo parseMethod = type.GetMethod("Parse");
             object value = parseMethod.Invoke(null, new object[] { valueText });
          
        • 或者你可以使用 .NET 提供的基础设施 组件模型。您可以获取 组件的类型转换器和使用 它是这样的:

             TypeConverter converter = TypeDescriptor.GetConverter(type);
             object value = converter.ConvertFromString(valueText);
          

        【讨论】:

          【解决方案5】:

          如前所述,这个问题太笼统了,一般不能解决。

          这里有一些选项:

          Type type = Type.GetType(typename);
          object o = Activator.CreateInstance(type);
          

          这将创建typename 所描述类型的实例。它调用该类型的无参数构造函数。 (缺点:并非所有对象都有无参数构造函数。此外,这确实使用value 设置对象的状态。)

          Type type = Type.GetType(typename);
          object o = Activator.CreateInstance(type, new[] { value });
          

          这将创建typename 所描述类型的实例。它调用该类型的构造函数,该构造函数接受string 类型的一个参数。 (缺点:并非所有对象都有这样的构造函数。例如,Int32 没有这样的构造函数,因此您会遇到运行时异常。)

          Type type = Type.GetType(typename);
          object o = Convert.ChangeType(value, type);
          

          这将尝试将字符串value 转换为所需类型的实例。这可能会导致InvalidCastExceptions。例如,Convert.ChangeType("4", typeof(FileStream)) 显然会失败,这是应该的。

          事实上,最后一个例子(创建一个FileStream 类型的实例,其初始状态由字符串"4" 确定)显示了一般问题是多么荒谬。有些构造/转换是无法完成的。

          您可能需要重新考虑您要解决的问题以避免陷入困境。

          【讨论】:

            【解决方案6】:

            这是你的想法吗?

            object result = Convert.ChangeType("4", Type.GetType("System.Int32"));
            

            【讨论】:

              【解决方案7】:

              这似乎是 Int32.Parse(string) 的工作。但要同意其他人的观点,这似乎是“独特的”,可能应该考虑手套。

              【讨论】:

                【解决方案8】:

                你的逻辑在这里似乎有点缺陷。显然,如果您稍后直接将对象转换为它的实际类型,那么您必须知道开始的类型。

                如果此问题还缺少其他内容,请详细说明,也许有比简单的“这没有多大意义”更合适的答案。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-06-30
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-03-09
                  • 2014-11-08
                  相关资源
                  最近更新 更多