【问题标题】:Dynamically create an object of <Type>动态创建 <Type> 的对象
【发布时间】:2010-10-09 08:58:52
【问题描述】:

我的数据库中有一个表,用于管理我的应用程序之间的关系。它的本质是非常基本的 - parentType,parentId,childType,childId ... 都是整数。我之前已经完成了这个设置,但是当我尝试链接 6 个不同的表时,我使用了 switch/case 设置。现在我有 30 个表正在尝试执行此操作,并且我希望能够执行此操作而不必在我的 switch 命令中编写 30 个 case 条目。

有没有一种方法可以使用字符串引用 .Net 类?我知道这是无效的(因为我已经尝试了几种变体):

Type t = Type.GetType("WebCore.Models.Page");
object page = new t();

我知道如何获取对象的类型,但是如何动态使用它来创建新对象?

【问题讨论】:

    标签: c# .net dynamic


    【解决方案1】:

    此链接应该会有所帮助:
    https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance

    Activator.CreateInstance 将创建一个指定类型的实例。

    您可以将其包装在这样的通用方法中:

    public T GetInstance<T>(string type)
    {
        return (T)Activator.CreateInstance(Type.GetType(type));
    }
    

    【讨论】:

    • 如果包含该类型的程序集尚未加载到 AppDomain 中,这将不起作用。
    • 此外,为了调用该方法,OP 必须在编译时访问该类型 - 原始问题询问如何在执行时从字符串创建实例。
    • 我只是根据问题中提供的示例来回答。
    • 啊,你是对的 - OP 似乎确实可以访问该类型!我的错误 - (-1) 已删除!
    • 您的示例还需要在编译时了解类型:)
    【解决方案2】:

    如果调用者知道该类型,则有一种比使用 Activator.CreateInstance 更好、更快的方法:您可以对指定它具有默认无参数构造函数的方法使用泛型约束。

    这样做是类型安全的,不需要反射。

    T CreateType<T>() where T : new()
    {
       return new T();
    }
    

    【讨论】:

    • 它不需要在源代码级别进行反射 - 但它在生成的 IL 中使用 Activator.CreateInstance。
    • 反射是必需的,因为指定的 OP 使用字符串来标识类型。
    【解决方案3】:
    public static T GetInstance<T>(params object[] args)
    {
         return (T)Activator.CreateInstance(typeof(T), args);
    }
    

    我会使用 Activator.CreateInstance() 而不是强制转换,因为 Activator 有一个泛型构造函数。

    【讨论】:

      【解决方案4】:

      你想使用Activator.CreateInstance

      这是一个如何工作的例子:

      using System;
      using System.Runtime.Remoting;
      
      class Program
      {
          static void Main()
          {
              ObjectHandle o = Activator.CreateInstance("mscorlib.dll", "System.Int32");
      
              Int32 i = (Int32)o.Unwrap();
          }
      }
      

      【讨论】:

        【解决方案5】:

        假设你有以下类型:

        public class Counter<T>
        {
          public T Value { get; set; }
        }
        

        并且具有该类型的程序集限定名,可以通过以下方式构造它:

        string typeName = typeof(Counter<>).AssemblyQualifiedName;
        Type t = Type.GetType(typeName);
        
        Counter<int> counter = 
          (Counter<int>)Activator.CreateInstance(
            t.MakeGenericType(typeof(int)));
        
        counter.Value++;
        Console.WriteLine(counter.Value);
        

        【讨论】:

          【解决方案6】:

          这是我编写的一个函数,它使用反射克隆 T 类型的记录。 这是一个非常简单的实现,我没有处理复杂的类型等。

           public static T Clone<T>(T original)
              {
                  T newObject = (T)Activator.CreateInstance(original.GetType());
          
                  foreach (var prop in original.GetType().GetProperties())
                  {
                      prop.SetValue(newObject, prop.GetValue(original));
                  }
          
                  return newObject;
              }
          

          我希望这可以帮助某人。

          阿萨夫

          【讨论】:

            猜你喜欢
            • 2012-09-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-08-18
            • 2010-10-15
            • 1970-01-01
            • 2020-10-11
            • 1970-01-01
            相关资源
            最近更新 更多