C# 中的参数化 System.Type 变量

我正在尝试在 C# 中创建一个工厂类,该类返回属于或扩展某个基本类型的对象。每次调用getInstance()工厂时我都需要实例化这种类型的新实例,所以我真的只想接受并存储类型本身。在 Java 中,我使用Class<? extends Base>来保存要创建的类,然后调用getInstance()它。


我了解如何使用 C# 中的 Activator 类从 a 创建新对象,System.Type但我不确定的部分是对类类型的约束。我希望能够只接受属于或扩展基类的类型。我意识到我可以更改工厂的 setter 以接受基本类型的实际对象,然后从中检索类型,但我真的不想实例化整个对象只是为了检索 Type 变量。


下面是一个小示例 Java 程序,只是为了演示我需要什么,以防我的问题不清楚。有没有办法在 C# 中做到这一点?


class Program {

   public static void main(String[] args) throws InstantiationException, IllegalAccessException {

         Factory.setClass(Base.class);

         Base b = Factory.getInstance();

         b.Print();


         Factory.setClass(Child.class);

         b = Factory.getInstance();

         b.Print();

      }

}


class Factory {

   private static Class<? extends Base> type;


   // What I want to do in C#.

   public static void setClass(Class<? extends Base> newType) {

      type = newType;

   }


   // What I don't want to have to do in C#.

   public static void setClassFromObject(Base newTypeObject) {

      type = newTypeObject.getClass();

   }


   public static Base getInstance() throws InstantiationException, IllegalAccessException {

      return type.newInstance();

   }

}


class Base {

   public void Print() {

      System.out.println("Hello from base.");

   }

}


class Child extends Base {

   @Override

   public void Print() {

      System.out.println("Hello from child.");

   }

}


翻翻过去那场雪
浏览 168回答 2
2回答

慕的地6264312

我看不到如何在编译时强制执行此操作,但如果您对运行时检查没问题,您可以这样做:class Factory&nbsp;{&nbsp; &nbsp; private static Type _type;&nbsp; &nbsp; public static void SetClass(Type t)&nbsp;&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (!(typeof(Base)).IsAssignableFrom(t))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new ArgumentException("type does not extend Base", nameof(t));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; _type = t;&nbsp; &nbsp; }&nbsp; &nbsp; public static Base GetInstance()&nbsp;&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return (Base)Activator.CreateInstance(_type);&nbsp; &nbsp; }}

郎朗坤

您可以使“GetInstance”方法动态化,以便在设置类时也设置方法。这样你就可以在运行时依赖泛型来获得正确的类型。它可能看起来像这样:public class Factory{&nbsp; &nbsp; private static Func<Base> _getInstance;&nbsp; &nbsp; //option if you want to pass in an instantiated value&nbsp; &nbsp; public static void SetClass<T>(T newType) where T : Base, new()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _getInstance = () => new T();&nbsp; &nbsp; }&nbsp; &nbsp; //option if you just want to give it a type&nbsp; &nbsp; public static void SetClass<T>() where T : Base, new()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _getInstance = () => new T();&nbsp; &nbsp; }&nbsp; &nbsp; public static Base GetInstance()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return _getInstance();&nbsp; &nbsp; }&nbsp; &nbsp; //you could just make GetInstance Generic as well, so you don't have to set the class first&nbsp; &nbsp; public static Base GetInstance<T>() where T : Base, new()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return new T();&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP