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

C# 如何在C中使用泛型返回接口#,c#,generic-programming,C#,Generic Programming,我是C#Generic概念的新手,我想使用Generic概念返回接口实现的类。下面是我的示例,它当前在没有泛型的情况下实现: 1) 返回接口的Factory类,该类有两种重载方法,它们接受不同的数据模型: public class Factory { public ICommon Init(DBInfoData dbInfoData) { return new ClassA(dbInfoData); } public ICommon Init(W

我是C#Generic概念的新手,我想使用Generic概念返回接口实现的类。下面是我的示例,它当前在没有泛型的情况下实现:

1) 返回接口的Factory类,该类有两种重载方法,它们接受不同的数据模型:

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();
    }
}
//=== 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; }
}
3) 数据模型类别如下:

//=== 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();
    }
}
//=== 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#的通用功能,在factory类中,我不想声明两个重载方法。使用单个方法,我可以基于数据模型pass返回ClassA或ClassB。

您可以编辑
Init
方法,而无需编辑任何其他内容。此方法将采用泛型类型参数
T
,该参数可以是任何类型。然后您可以使用
is
操作符,该操作符根据用于类型测试的。但是,您需要检查是否存在任何不受支持的
T
,因为您没有向传递的泛型类型添加任何约束。一个原始的实现将是:

公共类工厂
{
公共icommoninit(T infoData)
{
if(infoData是DBInfoData DBInfoData){
返回新的ClassA(dbInfoData);
}
如果(infoData是WebInfoData WebInfoData){
返回新的ClassB(webInfoData);
}
抛出新异常($“无法为{infoData.GetType().Name}类型的信息数据创建实例”);
}
}
为了测试它:

var factory=new factory();
var t1=factory.Init(新的DBInfoData());//将是甲级
var t2=factory.Init(新WebInfoData());//B类
为了使它更复杂,可以在泛型
T
类中引入,以确保只能传递适当的类型。对于当前的情况,您可以通过引入一个空接口(比如
iinfo-data
)为类
DBInfoData
WebInfoData
创建一个新的接口。然后您必须像这样继承您的类:

公共接口IInfoData{}
公共类DBInfoData:IInfoData
{
公共字符串服务器{get;set;}
公共字符串数据库{get;set;}
}
公共类WebInfoData:IInfoData
{
公共字符串URL{get;set;}
公共int端口{get;set;}
}
现在两者都继承自(实际上是“标记的”)基本接口。向工厂引入一个约束,通过添加我在上面链接的文档中所示的约束,只允许将
IInfoData
的后代作为参数传递(因此
DBInfoData
WebInfoData
):

公共类工厂
{
公共ICommon Init(T infoData),其中T:IInfoData
{
if(infoData是DBInfoData DBInfoData){
返回新的ClassA(dbInfoData);
}
如果(infoData是WebInfoData WebInfoData){
返回新的ClassB(webInfoData);
}
抛出新异常($“无法为{infoData.GetType().Name}类型的信息数据创建实例”);
}
}
除了
IInfoData
的后代之外的任何类型都将导致编译错误,您已经完成了。像我前面的例子一样使用它:

var factory=new factory();
var t1=factory.Init(新的DBInfoData());//将是甲级
var t2=factory.Init(新WebInfoData());//B类

您现在如何调用
工厂
方法?您是否只有两个数据模型,或者会有更多的数据模型?“我不想声明两个重载方法”。为什么呢?你给我们看的代码清晰易懂。我看不出在这种情况下使用泛型有什么好处。您是否在
工厂
中遗漏了一些您想要删除的重复代码?第二个@GeorgPatscheider的评论。在这里,泛型没有什么好处,除非你没有分享一些东西。坚持重载。@GeorgPatscheider:如前所述,我们希望实现泛型概念,这将减少重载方法,并且通过单个方法可以绑定适当的类。工厂代码中没有我遗漏的任何部分。我喜欢基于数据模型绑定类,所以我正在研究如何在这方面实现泛型概念。虽然这是可行的,但它违反了可靠的原则,好像您引入了
IInfoData
的新实现,您需要更新
Init
方法。话虽如此,您的代码根本就不是泛型的;它是一系列特定的实现,隐藏在一个通用接口后面。是的,就像工厂模式本身违背了坚实的原则一样,如果按照它的本意实现的话。看见