如何在 C# 中使用泛型 return 接口
How to return interface using generic in C#
我是 C# 泛型概念的新手,我想 return 使用泛型概念实现的接口 class。下面是我的例子,目前没有泛型实现:
1) Factory Class which return interface 和 this class 有两个重载方法接受不同的数据模型:
public class Factory
{
public ICommon Init(DBInfoData dbInfoData)
{
return new ClassA(dbInfoData);
}
public ICommon Init(WebInfoData webInfoData)
{
return new ClassB(webInfoData);
}
}
2)接口和接口实现了两个class如下:
//=== 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) 数据模型 class 如下:
//=== 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# 的通用功能 class 我不想声明两个重载方法。使用单一方法,我可以 return ClassA 或 ClassB 基于数据模型传递。
您可以编辑 Init
方法,而无需编辑任何其他内容。此方法将采用泛型类型参数 T
,它可以是任何类型。然后你可以使用is
运算符,它根据docs用来进行类型测试。但是,您需要检查任何不受支持的 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
为了使它更复杂,您可以通过引入空接口 IInfoData
来为 类 DBInfoData
和 WebInfoData
引入 type constraint on your generic T
class to make sure you can only pass appropriate types. For the current situation, you could create a marker interface。那么你必须像这样继承你的类:
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; }
}
现在两者都继承自(实际上 'marked by')您的基本接口。通过添加我在上面链接的文档中显示的约束,向您的工厂引入约束以仅允许 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
的后代之外的任何类型都会导致编译错误,您就完成了。像我之前的例子一样使用它:
var factory = new Factory();
var t1 = factory.Init(new DBInfoData()); // will be ClassA
var t2 = factory.Init(new WebInfoData()); // ClassB
我是 C# 泛型概念的新手,我想 return 使用泛型概念实现的接口 class。下面是我的例子,目前没有泛型实现:
1) Factory Class which return interface 和 this class 有两个重载方法接受不同的数据模型:
public class Factory
{
public ICommon Init(DBInfoData dbInfoData)
{
return new ClassA(dbInfoData);
}
public ICommon Init(WebInfoData webInfoData)
{
return new ClassB(webInfoData);
}
}
2)接口和接口实现了两个class如下:
//=== 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) 数据模型 class 如下:
//=== 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# 的通用功能 class 我不想声明两个重载方法。使用单一方法,我可以 return ClassA 或 ClassB 基于数据模型传递。
您可以编辑 Init
方法,而无需编辑任何其他内容。此方法将采用泛型类型参数 T
,它可以是任何类型。然后你可以使用is
运算符,它根据docs用来进行类型测试。但是,您需要检查任何不受支持的 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
为了使它更复杂,您可以通过引入空接口 IInfoData
来为 类 DBInfoData
和 WebInfoData
引入 type constraint on your generic T
class to make sure you can only pass appropriate types. For the current situation, you could create a marker interface。那么你必须像这样继承你的类:
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; }
}
现在两者都继承自(实际上 'marked by')您的基本接口。通过添加我在上面链接的文档中显示的约束,向您的工厂引入约束以仅允许 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
的后代之外的任何类型都会导致编译错误,您就完成了。像我之前的例子一样使用它:
var factory = new Factory();
var t1 = factory.Init(new DBInfoData()); // will be ClassA
var t2 = factory.Init(new WebInfoData()); // ClassB