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

C# 从方法返回更多继承的泛型类?,c#,generics,inheritance,covariance,C#,Generics,Inheritance,Covariance,我有这样的接口: public interface IImportModel { } public class MaterialImportProccessor : IImportProcessor<MaterialImportModel> { public void Process(MaterialImportModel model) { // do some logic here } } 和实现此接口的类: public class M

我有这样的接口:

public interface IImportModel
{
}
public class MaterialImportProccessor : IImportProcessor<MaterialImportModel>
{
    public void Process(MaterialImportModel model)
    {
        // do some logic here
    }
}
和实现此接口的类:

public class MaterialImportModel: IImportModel
{
    public string Name { get; set; }
}
public interface IImportProcessorFactory
{
    IImportProcessor<IImportModel> Get(Parameter parameter);
}
此外,我还为进口处理器提供接口:

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

因为它,我不能使进口处理器工厂通用

您是否尝试使用as操作符添加所提到的类似于强制转换的用户DevFlamur?

您应该更改为:

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;
         }
    }
}

更新

考虑为您的工厂使用
dynamic
关键字:

    public interface IImportProcessorFactory 
    {
        dynamic Get(Parameter parameter);
    }

    public class ImportProcessorFactory : IImportProcessorFactory
    {
        public dynamic Get(Parameter parameter)
        { 
            switch (parameter)
            {
                case Parameter.Materials:
                    return new MaterialImportProccessor() ; 

                case Parameter.Companies:
                    return new CompaniesImportProccessor();
                default:
                    return null;
            }
        }
    }
因此,您可以像这样使用它:

        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);
享受吧

更新2 这是我今天能做的最好的了

public interface IImportProcessor
{
     void Process();
}

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

public class ImportProcessor1 : IImportProcessor
{
    private readonly ImportModel1 data;
    public ImportProcessor1(ImportModel1 data) { this.data = data;}
    public void Process() => Console.WriteLine($"My name is {data.Name}");
}

public class ImportModel2{ public int Age { get; set; }}

public class ImportProcessor2 : IImportProcessor
{
    private readonly ImportModel2 data;

    public ImportProcessor2(ImportModel2 data) { this.data = data;}
    public void Process() => Console.WriteLine($"My age is {data.Age}");
}

public enum EType {One = 1, Two = 2}


public class ImportProcessorFactory
{
    public IImportProcessor Get(EType type, string file) 
    {   
        switch (type)
        {
            case EType.One: return new ImportProcessor1(JsonConvert.DeserializeObject<ImportModel1>(file));
            case EType.Two: return new ImportProcessor2(JsonConvert.DeserializeObject<ImportModel2>(file));
        }

        throw new NotImplementedException("Unable to work with '{type}'");
    }
}


class Program
{

    public static void Main() 
    {
        var f = new ImportProcessorFactory();

        var data1 = (EType.One, "{ Name: 'Vlad' }");
        var p1 = f.Get(data1.Item1, data1.Item2 );
        Console.WriteLine(p1.GetType());
        p1.Process();

        var data2 = (EType.Two, "{ Age: '20' }");

        var p2 = f.Get(data2.Item1, data2.Item2 );
        Console.WriteLine(p2.GetType());
        p2.Process();


    }
}
更新1 放下模型接口,让处理器取T

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

材料处理者应实现采用接口而非具体类的
过程
。否则它a)不符合合同,b)您将失去接口的好处:)


我决定添加额外的抽象类:

public abstract class ImportProcessor<TModel> : IImportProcessor<MaterialImportModel> where TModel: class
{
    public void Process(IImportModel model)
    {
        Process(model as TModel);
    }

    public abstract void Process(TModel model);
}


你试过增加演员阵容吗?是的,我试过了。但是在这种情况下有一个运行时错误。因为
IImportProcessor
不是由
MaterialImportProcessor
类实现的。是的,但是MaterialImportProcessor实现了IImportProcessor,其中MaterialImportModel实现了IImportModel。如果使用“out”关键字,则可以正常工作。例如:公共接口IImportProcessor,其中TModel:IImportModel;但我不能这样做,因为TModel是'Process()'方法的输入参数。在这种情况下,我必须为每个导入模型实现新的工厂。因为我不仅要导入材料,还要导入公司、用户等。我编辑了我的问题,解释了为什么我不能使用通用工厂。谢谢如果不能使用泛型类,则可以使用泛型方法
IImportProcessor Get(),其中TModel:IImportModel
不,我也不能使用泛型方法。因为在我尝试获取导入处理器的步骤中,我不知道在泛型方法中使用它的类型。我只有枚举。我想通过工厂中的枚举获得具体的导入处理器。所以您不应该使用泛型,您可以将接口转换为MaterialImportProcessor中的类。Process Method当我尝试使用'as'运算符时,工厂返回null而不是处理器的实例。当我使用显式转换时,我得到运行时异常。工厂应该返回的不仅仅是MaterialImportProcessor。它应该是通用的。因为我会有很多进口处理器。因此,我不能限制工厂使用MaterialImportModel。谢谢。但我想避免使用仿制药工厂。因为在步骤中,当我尝试获取导入处理器时,我不知道导入模型的具体类型。我只有枚举。工厂应通过此枚举将具体的导入处理器返回给我。我编辑了我的问题,并提供了有关如何使用factory的更多信息。@VladB现在再次检查,我修改了
MaterialImportProcessor
类的实现并简化了iThanks。我知道铸造的解决方案。但我想避免这样。如果我找不到更好的解决办法,我将不得不接受。我还需要通用IImportProcessor,因为我计划在DI容器中注册所有导入处理器。因此,它们应该参数化。否则,我只能登记一个。@ VLADB然后考虑使用动态,我更新小提琴URL再次希望它有助于这次:)是的。我同意。如果我无法找到其他解决方案,我将不得不使用这种方法。但在这种情况下,我必须将IImportModel转换为每个处理器中的具体类,这是我想要避免的。我也可以使用justobject。谢谢你的帮助。如果你必须施放,为什么不停止假装这里有接口呢?只要使用具体的类。如果您正在为
Name
进行转换,则将其作为模型接口的一部分。我添加接口只是为了编写通用工厂。我想有一个工厂,它将返回具体的进口处理器的一些输入参数。我将有很多模型导入,其中每一个都与具体类型的作品。在工厂里我不能使用混凝土类型。“通用工厂”-通用!=接口。让我们把它变成通用的。
ImportProcessor1
My name is Vlad
ImportProcessor2
My age is 20
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();
}
public interface IImportProcessor
{
    void Process(IImportModel model);
}
public class MaterialImportProcessor : IImportProcessor
{
    public void Process(IImportModel model)
    {
        // do some logic here
    }
}
public abstract class ImportProcessor<TModel> : IImportProcessor<MaterialImportModel> where TModel: class
{
    public void Process(IImportModel model)
    {
        Process(model as TModel);
    }

    public abstract void Process(TModel model);
}
public class MaterialImportProccessor : ImportProcessor<MaterialImportModel>
{
    public override void Process(MaterialImportModel model)
    {

    }
}