如何使用约束实现泛型方法

5ea*_*rch 5 c# generics constraints c#-4.0

从我的标题可能有点难以理解我想要实现的目标,所以我会更详细地介绍一下。

我有以下界面:

public interface IModelBuilder<T>
    where T : IStandardTemplateTemplate
{
    M Build<M>(T pTemplate, params object[] pParams) where M : BaseModel;
}
Run Code Online (Sandbox Code Playgroud)

现在我想在我的实际构建器中实现接口。我用来映射不同对象类型的构建器。所以这看起来如下:

public class BusinessModelBuilder : IModelBuilder<IBusinessTemplate>
{
    public virtual M Build<M>(IBusinessTemplate pTemplate, params object[] pParams) where M : BussinessModel
    {
        var businessModel = Activator.CreateInstance<M>();

        // map data

        return businessModel;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在的问题如下。我无法让约束发挥作用。由于我在接口上定义了约束,它不会让我在实​​际方法上使用不同的约束,即使我的 BusinessModel 继承自 BaseModel。它一直告诉我我的约束 M 必须匹配来自接口的约束。我尝试了几种不同的方法,但似乎都不起作用。

有谁知道这是否或如何实现?我只想在界面中告诉我的约束,允许继承模型。

Ser*_*rvy 5

这是您的问题的一个简短但完整的示例:

public class Parent { }
public class Child { }

public interface Interface
{
    void Foo<T>() where T : Parent;
}

public class Implementation : Interface
{
    public void Foo<T>() where T : Child
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

这不会编译,原因与您的不会编译相同。接口方法的实现必须对泛型参数有完全相同的约束,它不能有更严格的约束。

您的Build方法只能将类型限制为BaseModel,而不是BussinessModel

如果您更改IModelBuilder接口以添加额外的类级别通用参数,然后将用作约束,则可以获得所需的功能:

public interface IModelBuilder<T, Model>
    where T : IStandardTemplateTemplate
    where Model : BaseModel
{
    M Build<M>(T pTemplate, params object[] pParams) where M : Model;
}    

public class BusinessModelBuilder : IModelBuilder<IBusinessTemplate, BussinessModel>
{
    public virtual M Build<M>(IBusinessTemplate pTemplate, params object[] pParams)
        where M : BussinessModel
    {
        var businessModel = Activator.CreateInstance<M>();

        // map data

        return businessModel;
    }
}
Run Code Online (Sandbox Code Playgroud)

该解决方案部分基于Reed 的回答,但更进一步。