[英]Using a type to instantiate a derived class which uses restricted generics
我正在使用通用工廠類,其中通用部分是正在使用的派生類。 正常用法很明確: BaseClass<DerivedA> C = new BaseClass<DerivedA>().
現在雖然我試圖將屬性注入到我使用這些類的類中。 為此,我嘗試將Type作為參數(以便我可以注入正在使用的派生類)。
現在雖然我有點不知所措,盡管我正在尋找自己的例子和自己。 而我現在想知道:這樣的構造是否可以使用? 如果是這樣,我如何實例化該類並使用Exists和ExistsB?
用法:
public class MyMainClass
{
object _ClassInstance; // BaseClass<DerivedA> or BaseClass<DerivedB>
public MyyMainClass(Type typeIWant)
{
.....
}
}
....
MyMainClass a = new MyMainClass(typeof(DerivedA));
MyMainClass b = new MyMainClass(typeof(DerivedB));
通用類:
public abstract class BaseClass<T> where T: BaseClass<T>, new()
{
...
public bool Exists(int a) {...}
}
派生類:
public class DerivedA :BaseClass<DerivedA>
{
...
}
public class DerivedB :BaseClass<DerivedB>
{
...
public bool ExistsB(string a) {...}
}
您可以使用以下方法創建任何類型的實例:
_ClassInstance = Activator.CreateInstance(typeIWant)
但是不建議使用它,因為當您想要使用其中一種BaseClass方法時,您將永遠檢查其類型並進行轉換。 如果您能夠更改主類以獲取類型參數,它應如下所示:
public class MyMainClass<T> where T: BaseClass<T>, new()
{
T _ClassInstance; // BaseClass<DerivedA> or BaseClass<DerivedB>
public MyMainClass()
{
_ClassInstance = new T();
}
}
這將允許您使用BaseClass上定義的任何方法。 如果你想使用ExistsB,那么你仍然需要在運行時檢查它的類型並進行轉換。 我會推薦這樣的東西:
if (_ClassInstance is DerivedB derivedB)
derivedB.ExistsB("...");
如果你真的需要編譯時檢查,我會推薦它,你的類需要改變。 您不能僅使用對基類的引用來訪問派生類上定義的方法或屬性。
這是你想要的嗎?
Object instance1 = Activator.CreateInstance<Object>();
Object instance2 = Activator.CreateInstance(typeof(object));
我建議你使用getType
來獲取一個類型名稱。 如果您升級繼承(從DerivedB等繼承另一個類),如果使用getType
您可以確保僅為DerivedB類型的實例調用此方法。
MyMainClass b = new MyMainClass(typeof(DerivedB));
if(b.GetType() == typeof(DerivedB))
b.ExistsB(...);
這是抽象類的主要問題 - 您共享接口和實現。 但在您的情況下,您強烈依賴於不同的接口。 要簡化問題,只需看看你真正想要的東西:
public interface IExistable<in TValue>
{
bool Exists(TValue value);
}
public interface IDerivedA : IExistable<int>
{
}
public interface IDerivedB : IExistable<int>, IExistable<string>
{
}
正如您所看到的,您使用兩個接口過度復雜IDerivedB,即,您的MainClass在某些情況下依賴於IDerivedB。 擴展接口也不錯,你只是錯誤地使用它。 所以你必須做的是為你的MainClass定義接口:
public interface IMainClass
{
//some methods here
}
並創建兩個實現:
public class ConcreteMainClass : CommonMainClass //you can derive from common, delegate to inner instance or implement interface from scratch - you decide depending on situation
{
private readonly IDerivedB _instance;
public ConcreteMainClass(IDerivedB instance) : base(instance)
{
_instance = instance;
}
//you can override some logic here depending on IExistable<string> from IDerivedB
}
public class CommonMainClass : IMainClass
{
private readonly IExistable<int> _instance;
public CommonMainClass(IExistable<int> instance)
{
_instance = instance;
}
//this is where you don't depend on IExistable<string>
}
這樣你就可以編寫更清晰的代碼:
IMainClass a = new CommonMainClass(new DerivedA());
IMainClass b = new ConcreteMainClass(new DerivedB());
PS :最好將依賴關系傳遞給類生命周期的上層,而不是在內部激活它,這樣你就可以使用工廠為你創建它們甚至是依賴注入。
PS2 :在抽象類之前使用接口。 接口/構造函數/方法描述了您的整體依賴關系。 另一方面,抽象類只是重用實現的一種方式 - 它們不是用來定義接口或者你如何使用類,你可以使整個主體私有/受保護而不會分享任何東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.