[英]Parameterized System.Type Variable in C#
我正在嘗試在C#中創建一個工廠類,該工廠類返回的對象是或擴展了某種基本類型。 每當我在工廠調用getInstance()
,我都需要實例化此類型的新實例,因此我真的只想接受並存儲該類型本身。 在Java中,我使用了Class<? extends Base>
Class<? extends Base>
來保存要創建的類,然后在其上調用getInstance()
。
我了解如何在C#中使用Activator類從System.Type
創建新對象,但是我不確定的部分是對類類型的約束。 我希望只能接受屬於或擴展基類的Type。 我意識到我可以在工廠中將設置器更改為接受基本類型的實際對象,然后從中檢索類型,但是我並不是真的想實例化整個對象只是為了檢索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.");
}
}
我看不到如何在編譯時強制執行此操作,但是如果您可以通過運行時檢查確定,則可以這樣做:
class Factory
{
private static Type _type;
public static void SetClass(Type t)
{
if (!(typeof(Base)).IsAssignableFrom(t))
{
throw new ArgumentException("type does not extend Base", nameof(t));
}
_type = t;
}
public static Base GetInstance()
{
return (Base)Activator.CreateInstance(_type);
}
}
您可以使“ GetInstance”方法動態化,以便在設置類時也可以設置該方法。 這樣,您可以在運行時依賴泛型來獲取正確的類型。 它可能看起來像這樣:
public class Factory
{
private static Func<Base> _getInstance;
//option if you want to pass in an instantiated value
public static void SetClass<T>(T newType) where T : Base, new()
{
_getInstance = () => new T();
}
//option if you just want to give it a type
public static void SetClass<T>() where T : Base, new()
{
_getInstance = () => new T();
}
public static Base GetInstance()
{
return _getInstance();
}
//you could just make GetInstance Generic as well, so you don't have to set the class first
public static Base GetInstance<T>() where T : Base, new()
{
return new T();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.