簡體   English   中英

從通用基類派生的通用類

[英]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 { ... }

其中, TaxServiceInfoTaxServiceProviderConfig用於支持TaxServiceProvider類。

我想從TaxServiceProvider創建派生類SpecialTaxServiceProvder (非抽象), TaxServiceProvider也是通用的,與TaxServiceProvider相同,並且將SpecialTaxServiceInfoSpecialTaxServiceProviderConfig作為類型。

我想在SpecialTaxServiceProvider實現GetTaxConfig ,以便GetTax返回類型SpecialTaxServiceInfo並且Config類型為SpecialTaxServiceProviderConfig

然后,我將創建一個從SpecialTaxServiceProvider派生的附加類以及從SpecialTaxServiceInfoSpecialTaxServiceProviderConfig派生的類

public class A_SpecialTaxServiceProvider : SpecialTaxServiceProvider<A_SpecialTaxServiceProviderConfig, A_SpecialTaxServiceInfo>
{ ... }
public class A_SpecialTaxServiceProviderConfig : SpecialTaxServiceProviderConfig { ... }
public class A_SpecialTaxServiceInfo : SpecialTaxServiceInfo { ... }

其中, GetTax返回類型A_SpecialTaxServiceInfo ,而A_SpecialTaxServiceInfoConfig的類型為A_SpecialTaxServiceProviderConfig

我已經研究了C#中的協方差和泛型類型類的語法,但是我不確定我要執行的操作是否在該語言中是不可能的,或者我只是不知道正確的設置方法。

  1. 更改SpecialTaxServiceProvider並將TS傳遞給TaxServiceProvider

     public class SpecialTaxServiceProvider<T, S> : TaxServiceProvider<T, S> where T : SpecialTaxServiceProviderConfig where S : SpecialTaxServiceInfo { public override S GetTax(int zipCode) { return null; } } 
  2. 實現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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM