[英]Derived generic class from generic base class
假設以下課程
// What I have created ...
public abstract class TaxServiceProvider<T, S>
where T : TaxServiceProviderConfig
where S : TaxServiceInfo
{
protected T Config { get; set; }
public abstract S GetTax(int zipCode);
}
public abstract class TaxServiceInfo { ... }
public abstract class TaxServiceProviderConfig { ... }
// What I want to create ...
public class SpecialTaxServiceProvider<T, S> : TaxServiceProvider<SpecialTaxServiceProviderConfig, SpecialTaxServiceInfo>
where T : SpecialTaxServiceProviderConfig
where S : SpecialTaxServiceInfo
{ ... }
public class SpecialTaxServiceInfo : TaxServiceInfo { ... }
public class SpecialTaxServiceProviderConfig : TaxServiceProviderConfig { ... }
其中, TaxServiceInfo
和TaxServiceProviderConfig
用於支持TaxServiceProvider
類。
我想從TaxServiceProvider
創建派生類SpecialTaxServiceProvder
(非抽象), TaxServiceProvider
也是通用的,與TaxServiceProvider
相同,並且將SpecialTaxServiceInfo
和SpecialTaxServiceProviderConfig
作為類型。
我想在SpecialTaxServiceProvider
實現GetTax
和Config
,以便GetTax
返回類型SpecialTaxServiceInfo
並且Config
類型為SpecialTaxServiceProviderConfig
然后,我將創建一個從SpecialTaxServiceProvider
派生的附加類以及從SpecialTaxServiceInfo
和SpecialTaxServiceProviderConfig
派生的類
public class A_SpecialTaxServiceProvider : SpecialTaxServiceProvider<A_SpecialTaxServiceProviderConfig, A_SpecialTaxServiceInfo>
{ ... }
public class A_SpecialTaxServiceProviderConfig : SpecialTaxServiceProviderConfig { ... }
public class A_SpecialTaxServiceInfo : SpecialTaxServiceInfo { ... }
其中, GetTax
返回類型A_SpecialTaxServiceInfo
,而A_SpecialTaxServiceInfo
的Config
的類型為A_SpecialTaxServiceProviderConfig
我已經研究了C#中的協方差和泛型類型類的語法,但是我不確定我要執行的操作是否在該語言中是不可能的,或者我只是不知道正確的設置方法。
更改SpecialTaxServiceProvider
並將T
和S
傳遞給TaxServiceProvider
:
public class SpecialTaxServiceProvider<T, S> : TaxServiceProvider<T, S> where T : SpecialTaxServiceProviderConfig where S : SpecialTaxServiceInfo { public override S GetTax(int zipCode) { return null; } }
實現A_SpecialTaxServiceProvider
並覆蓋GetTax
:
public class A_SpecialTaxServiceProvider : SpecialTaxServiceProvider<A_SpecialTaxServiceProviderConfig, A_SpecialTaxServiceInfo> { public override A_SpecialTaxServiceInfo GetTax(int zipCode) { return null; } }
它阻止您創建
public class A_SpecialTaxServiceProvider : SpecialTaxServiceProvider<A_SpecialTaxServiceProviderConfig, TaxServiceInfo>
有以下錯誤:
在通用類型或方法“ Project.SpecialTaxServiceProvider”中,類型“ Project.TaxServiceInfo”不能用作類型參數“ S”。 從“ Project.TaxServiceInfo”到“ Project.SpecialTaxServiceInfo”沒有隱式引用轉換。
我決定在構造函數中使用函數委托,以允許我傳入工廠方法來創建我的泛型類型。
這就是我最終得到的
// Tier 1 of my class hierarchy
public abstract class TaxServiceProvider<C, I>
where C : TaxServiceProviderConfig
where I : TaxServiceInfo
{
protected C Config { get; set; }
public abstract I GetTax(int zipCode);
}
public abstract class TaxServiceInfo {
public TaxServiceInfo(string param1, string param2, int param3, ect...) {
...
}
}
public abstract class TaxServiceProviderConfig { ... }
// Tier 2 of my class hierarchy
public class DerivedTaxServiceProvider<C, I> : TaxServiceProvider<C, I>
where C : DerivedTaxServiceProviderConfig
where I : DerivedTaxServiceInfo
{
protected Func<S, string, string, int, ect...> Factory;
public DerivedTaxServiceProvider (C config, Func<I, string, string, int, ect...> factory) {
Config = config;
Factory = factory;
}
public override I GetTax(int zipCode) {
...
I taxServiceInfo = Factory("param1", "param2", 3, ect...);
...
return I;
}
}
public class DerivedTaxServiceInfo : TaxServiceInfo {
public DerivedTaxServiceInfo(string param1, string param2, int param3, ect...)
: base(param1, param2, param3, ect...)
{ ... }
}
public class DerivedTaxServiceProviderConfig : TaxServiceProviderConfig { ... }
// Tier 3 of my class hierarchy
public class ConcreteTaxServiceProvider : DerivedTaxServiceProvider<ConcreteTaxServiceProviderConfig, ConcreteTaxServiceInfo> {
public ConcreteTaxServiceProvider(ConcreteTaxServiceProviderConfig config, Func<ConcreteTaxServiceInfo, string, string, int, ect...> factory) {
Config = config;
Factory = factory;
}
public override ConcreteTaxServiceInfo GetTax(int zipCode) {
return base.GetTax(zipCode);
}
}
public class ConcreteTaxServiceInfo : DerivedTaxServiceInfo {
public ConcreteTaxServiceInfo(string param1, string param2, int param3, ect...)
: base(param1, param2, param3, ect...)
{ ... }
public static ConcreteTaxServiceInfo CreateConcreteTaxServiceInfo(string param1, string param2, int param3, ect...) {
return new ConcreteTaxServiceInfo(param1, param2, param3, etc...);
}
}
public class ConcreteTaxServiceProviderConfig : DerivedTaxServiceProviderConfig { ... }
// Implementation of my class hierarchies
public void method() {
ConcreteTaxServiceProviderConfig() config = new ConcreteTaxServiceProviderConfig();
ConcreteTaxServiceProvider provider = new ConcreteTaxServiceProvider(config, ConcreteTaxServiceInfo.CreateConcreteTaxServiceInfo);
ConcreteTaxServiceInfo serviceInfo = provider.GetTax(99939);
}
所以基本上我有2個級別的泛型類。 二級提供程序類重寫了“ GetTax”的基本抽象方法,但是我不希望它返回具體的類型,因為那樣我就不能在從其繼承的類中干凈地調用該方法。 在具體的(第3級)Provider中調用“ GetTax”時,我將不得不將派生的ServiceInfo轉換為ConcreteServiceInfo類型。
只要我在Info類中有一個與我的委托人匹配的構造函數,無論該Info類處於什么子類級別(在第二層以下),我都可以將其輸入到提供程序中並使用第二層的Provider類GetTax方法。
此工廠方法在Provider構造函數的參數列表中看起來很丑陋,並且創建Info類的靜態方法似乎很尷尬,但這確實可以解決問題!
這是我咨詢以解決此問題的一個SO問題: C#泛型問題-在構造函數中使用參數更新泛型類型
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.