从方法返回更多继承的泛型类?

问题描述 投票:0回答:4

我有这样的界面:

public interface IImportModel
{
}

和实现此接口的类:

public class MaterialImportModel: IImportModel
{
    public string Name { get; set; }
}

而且我还有导入处理器的接口:

public interface IImportProcessor<TModel> where TModel: IImportModel
{
    void Process(TModel model);
}

并且有此接口的实现之一:

public class MaterialImportProccessor : IImportProcessor<MaterialImportModel>
{
    public void Process(MaterialImportModel model)
    {
        // do some logic here
    }
}

现在,我想创建Factory来实例化此类处理器。我有界面:

public interface IImportProcessorFactory
{
    IImportProcessor<IImportModel> Get(Parameter parameter);
}

而且我正在尝试创建实现:

    public class ImportProcessorFactory : IImportProcessorFactory
    {
        public IImportProcessor<IImportModel> Get(Parameter parameter)
        {
             switch (Parameter) 
             {
                case "Materials":
                     IImportProcessor<IImportModel> processor = new MaterialImportProccessor();
                     return processor;

                case "Companies":
                    IImportProcessor<IImportModel> processor = new CompaniesImportProccessor();
                    return processor;
             }
        }
    }

但是我有例外:

错误CS0266无法将类型'MaterialImportProccessor'隐式转换为IImportProcessor<IImportModel>。存在显式转换(您是否缺少演员表?)

是的。但是我无法使用out关键字进行IImportProcessor协方差,因为我将TModel用作Process(TModel method)方法的输入参数。

是否有任何方法可以重构此代码以使其正常工作?

编辑

我决定提供有关我打算如何使用该工厂的更多信息。

var deserializer = _deserializerFactory.Get(/*some parameters*/);
var importProcessor = _importProcessorFactory.Get(someEunmValue);

var data = deserializer.Deserialize(file);
importProcessor.Process(data);

因此,我无法使导入处理器出厂通用。

c# generics inheritance covariance
4个回答
0
投票

评论后更新。

删除模型接口并使处理器取T

public interface IImportProcessor<T>
{
    void Process(T model);
}

通过这种设置,东西应该放在一起。

public interface IImportProcessor<T>
{
    void Process(T model);
}

public class MaterialImportModel
{
    public string Name { get; set; }
}

public class MaterialImportProccessor : IImportProcessor<MaterialImportModel>
{
    public void Process(MaterialImportModel model)
    {
        // do some logic here
    }
}

public interface IImportProcessorFactory<T>
{
    IImportProcessor<T> Get();
}

public class ImportProcessorFactory : IImportProcessorFactory<MaterialImportModel>
{
    public IImportProcessor<MaterialImportModel> Get() => new MaterialImportProccessor();
}

(旧答案)

[我认为使IImportProcessor为非泛型将使您的模型更加简单,并消除了一整类问题。

public interface IImportProcessor
{
    void Process(IImportModel model);
}

物料处理器应实现带有接口的Process,而不是具体的类。否则它a)不符合合同要求,并且b)您摆脱了接口的好处:)。

public class MaterialImportProcessor : IImportProcessor
{
    public void Process(IImportModel model)
    {
        // do some logic here
    }
}

0
投票

您应更改为:

public interface IImportModel
{

}

public class MaterialImportModel: IImportModel
{
    public string Name { get; set; }
}

public class CompanieImportModel: IImportModel
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public interface IImportProcessor
{
     void Process(IImportModel model);
}

public class MaterialImportProccessor : IImportProcessor
{
    public void Process(IImportModel model)
    {
        var obj = (MaterialImportModel) model;

        // do some logic here
    }
}

public interface IImportProcessorFactory
{
    IImportProcessor Get();
}


public class ImportProcessorFactory 
{
    public IImportProcessor Get(Parameter parameter)
    {
         switch (Parameter) 
         {
            case "Materials":
                 IImportProcessor processor = new MaterialImportProccessor();
                 return processor;

            case "Companies":
                IImportProcessor processor = new CompaniesImportProccessor();
                return processor;
         }
    }
}

0
投票

UPDATE

https://dotnetfiddle.net/LflrsX

我现在更新了代码,因此您可以类似于以下方式使用它:

        var factory = new ImportProcessorFactory();
        var material = factory.Get(Parameter.Materials);
        var company = factory.Get(Parameter.Companies);


        var model = new MaterialImportModel();
        model.MaterialName = " Metal ";
        material.Process(model);

        var cModel = new CompanyImportModel();
        cModel.CompanyName = "Build Metal Company";
        company.Process(cModel);

享受!


-1
投票

您是否尝试使用as运算符添加像用户DevFlamur这样的演员表?

© www.soinside.com 2019 - 2024. All rights reserved.