簡體   English   中英

如何在C#中使用泛型返回接口

[英]How to return interface using generic in C#

我是 C# 通用概念的新手,我想使用通用概念返回接口實現的類。 下面是我目前沒有泛型實現的示例:

1) 返回接口的工廠類,這個類有兩個重載方法,接受不同的數據模型:

public class Factory
{
    public ICommon Init(DBInfoData dbInfoData)
    {
        return new ClassA(dbInfoData);
    }

    public ICommon Init(WebInfoData webInfoData)
    {
        return new ClassB(webInfoData);
    }
}

2)接口和接口實現兩個類如下:

//=== Common Interface
public interface ICommon
{
    void MethodA();
    void MethodB();
}

//=== Internal access only ClassA
internal class ClassA : ICommon
{
    private DBInfoData _DBInfoData = null;
    public ClassA(DBInfoData dbInfoData)
    {
        _DBInfoData = dbInfoData;
    }

    public void MethodA()
    {
        throw new NotImplementedException();
    }

    public void MethodB()
    {
        throw new NotImplementedException();
    }
}

//=== Internal access only ClassB
internal class ClassB : ICommon
{
    private WebInfoData _WebInfoData = null;

    public ClassB(WebInfoData webInfoData)
    {
        _WebInfoData = webInfoData;
    }

    public void MethodA()
    {
        throw new NotImplementedException();
    }

    public void MethodB()
    {
        throw new NotImplementedException();
    }
}

3) 數據模型類如下:

//=== Database Information
public class DBInfoData
{
    public string Server { get; set; }
    public string Database { get; set; }
}

//=== Web Server Information
public class WebInfoData
{
    public string URL { get; set; }
    public int Port { get; set; }
}

現在我想在工廠類中實現 C# 的通用功能,我不想聲明兩個重載方法。 使用單一方法,我可以根據數據模型傳遞返回 ClassA 或 ClassB。

您可以編輯Init方法而無需編輯任何其他內容。 此方法將采用泛型類型參數T ,它可以是任何類型。 然后您可以使用is運算符,根據用於類型測試的文檔 但是,您需要檢查任何不受支持的T類型,因為您沒有向傳遞的泛型類型添加任何約束。 原始實現將是:

public class Factory
{
    public ICommon Init<T>(T infoData)
    {
        if (infoData is DBInfoData dbInfoData) {
            return new ClassA(dbInfoData);
        }
        if (infoData is WebInfoData webInfoData) {
            return new ClassB(webInfoData);
        }

        throw new Exception($"Cannot create instance for info data of type {infoData.GetType().Name}");
    }
}

並測試它:

    var factory = new Factory();

    var t1 = factory.Init(new DBInfoData()); // will be ClassA
    var t2 = factory.Init(new WebInfoData()); // ClassB

為了使其更復雜,您可以在泛型T類上引入類型約束,以確保只能傳遞適當的類型。 對於當前情況,您可以通過引入一個空接口(例如IInfoData為您的類DBInfoDataWebInfoData創建一個標記接口 然后你必須像這樣繼承你的類:

public interface IInfoData {}

public class DBInfoData : IInfoData
{
    public string Server { get; set; }
    public string Database { get; set; }
}

public class WebInfoData : IInfoData
{
    public string URL { get; set; }
    public int Port { get; set; }
}

現在兩者都繼承自(實際上是“標記為”)您的基本接口。 通過添加我上面鏈接的文檔中顯示的約束,向您的工廠引入一個約束,以僅允許IInfoData后代作為參數傳遞(因此無論是DBInfoData還是WebInfoData ):

public class Factory
{
    public ICommon Init<T>(T infoData) where T: IInfoData
    {
        if (infoData is DBInfoData dbInfoData) {
            return new ClassA(dbInfoData);
        }
        if (infoData is WebInfoData webInfoData) {
            return new ClassB(webInfoData);
        }

        throw new Exception($"Cannot create instance for info data of type {infoData.GetType().Name}");
    }
}

除了IInfoData的后代之外的任何類型IInfoData將導致編譯錯誤,您就大功告成了。 像我之前的例子一樣使用它:

    var factory = new Factory();

    var t1 = factory.Init(new DBInfoData()); // will be ClassA
    var t2 = factory.Init(new WebInfoData()); // ClassB

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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