[英]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
為您的類DBInfoData
和WebInfoData
創建一個標記接口。 然后你必須像這樣繼承你的類:
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.