繁体   English   中英

如何指向基础类<T>在通用工厂

[英]How to point to underlying class of <T> in generic factory

吃了些蔬菜:

public interface IVegetable
{

}

public class Potato : IVegetable
{

}

public class Onion : IVegetable
{

}

我们将专注于洋葱并对其进行处理:我有一个通用蔬菜处理器的通用接口和一个特定于洋葱的接口:

public interface IVegetableProcessor<T> where T : IVegetable
{
    string GetColor(T vegetable);
}

public interface IOnionProcessor : IVegetableProcessor<Onion>
{
    void MakeCry(Onion onion);
}

public class OnionProcessor : IOnionProcessor
{
    public string GetColor(Onion onion)
    {
        return "Purple";
    }

    public void MakeCry(Onion onion)
    {
        Console.WriteLine($"{onion} made you cry!");
    }
}

以及通用工厂:

interface IVegetableProcessorFactory
{
    IVegetableProcessor<T> GetVegetableProcessor<T>(T vegetable) where T : IVegetable;
}

internal class VegetableProcessorFactory : IVegetableProcessorFactory
{
    public IVegetableProcessor<T> GetVegetableProcessor<T>(T vegetable) where T : IVegetable
    {
        object processor = vegetable switch
        {
            Onion => new OnionProcessor(),
            _ => throw new NotImplementedException($"Other vegetables not here yet")
        };

        return (IVegetableProcessor<T>)processor; //this will fail later
    }
}

最后这不起作用:

static void Main(string[] args)
{
    var onion = new Onion() as IVegetable;
    var factory = new VegetableProcessorFactory();

    var processor = factory.GetVegetableProcessor(onion);

    Console.WriteLine(processor.GetColor(onion));
    Console.ReadLine();
}

错误是:

System.InvalidCastException: 'Unable to cast object of type 'OnionProcessor' to type 'IVegetableProcessor`1[Vegetables.Program+IVegetable]'.'

如何让它理解 IVegetable 的底层类并将处理器转换为它的相应类型?

您的输入已经是逆变的,但是通过将您的 Onion 实例转换为IVegetable ,它不再能够在您的工厂中被转换回IVetetableProcessor<T> ,因为此时您需要IVetetableProcessor<Onion> ,但是您拥有的是IVegetableProcessor<IVegetable> ,并且您的界面不是协变的。

通过简单地将new Onion的初始转换删除到IVegetable ,您的代码将按原样工作:

static void Main(string[] args)
{
    var onion = new Onion();
    var factory = new VegetableProcessorFactory();

    var processor = factory.GetVegetableProcessor(onion);

    Console.WriteLine(processor.GetColor(onion));
    Console.ReadLine();
}

public interface IVegetable { }
public class Potato : IVegetable { }
public class Onion : IVegetable { }

public interface IVegetableProcessor<T> where T : IVegetable
{
    string GetColor(T vegetable);
}

public interface IOnionProcessor : IVegetableProcessor<Onion>
{
    void MakeCry();
}

public class OnionProcessor : IOnionProcessor
{
    public string GetColor(Onion vegetable)
    {
        return "Purple";
    }

    public void MakeCry()
    {
        Console.WriteLine("You cry now!");
    }
}

interface IVegetableProcessorFactory
{
    IVegetableProcessor<T> GetVegetableProcessor<T>(T vegetable) where T : IVegetable;
}

internal class VegetableProcessorFactory : IVegetableProcessorFactory
{
    public IVegetableProcessor<T> GetVegetableProcessor<T>(T vegetable) where T : IVegetable
    {
        var processor = vegetable switch
        {
            Onion => new OnionProcessor(),
            _ => throw new NotImplementedException($"Other vegetables not here yet")
        };

        return (IVegetableProcessor<T>)processor;
    }
}

你必须首先投射的事实是你暗示你的作品中有什么东西被破坏了。 正如 Selvin 在评论中提到的,实现IVegetableProcessor<Onion>与实现IVegetableProcessor<IVegetable>

您的处理器接口应该实现IVegetableProcessor<IVegetable>并采用 IVegetable 实例,允许输入参数的逆变:

public interface IVegetableProcessor<T> where T : IVegetable
{
    string GetColor(T vegetable);
}

public interface IOnionProcessor : IVegetableProcessor<IVegetable>
{
    void MakeCry();
}

public class OnionProcessor : IOnionProcessor
{
    public string GetColor(IVegetable vegetable)
    {
        return "Purple";
    }

    public void MakeCry()
    {
        Console.WriteLine("You cry now!");
    }
}

interface IVegetableProcessorFactory
{
    IVegetableProcessor<IVegetable> GetVegetableProcessor(IVegetable vegetable);
}

internal class VegetableProcessorFactory : IVegetableProcessorFactory
{
    public IVegetableProcessor<IVegetable> GetVegetableProcessor(IVegetable vegetable)
    {
        var processor = vegetable switch
        {
            Onion => new OnionProcessor(),
            _ => throw new NotImplementedException($"Other vegetables not here yet")
        };

        return processor;
    }
}

通过以下方式运行时,这会正确输出“Purple”:

static void Main(string[] args)
{
    var onion = new Onion();
    var factory = new VegetableProcessorFactory();

    var processor = factory.GetVegetableProcessor(onion);

    Console.WriteLine(processor.GetColor(onion));
    Console.ReadLine();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM