简体   繁体   English

具有通用接口的工厂方法

[英]Factory Method with Generic Interface

I have two different types of item: Picture and Video.我有两种不同类型的项目:图片和视频。 In order to manage them, I have created an interface and two classes which implement it为了管理它们,我创建了一个接口和两个实现它的类

public interface Item{
}

public class ItemPicture: Item{
}

public class ItemVideo: Item {
}

Now I have some classes to manage that items, that inherit from a manager interface现在我有一些类来管理那些从管理器接口继承的项目

public interface ItemManager<T>{
   IList<T> FGetByGroup(string idgroup);
}

public class ItemManagerPictures : IItemManager<ItemPicture>{
   public IList<ItemFoto> FGetByGroup(string idgroup){
      ...
   }
}
public class ItemManagerVideos: IItemManager<ItemVideo>{
   public IList<ItemVideo> FGetByGroup(string idgroup){
      ...
   }
}

In order to have a factory method which creates the appropriate object, I have created this class为了有一个创建适当对象的工厂方法,我创建了这个类

public class ItemManagerCreator
    {
        public static IItemManager<Item> MakeItemManager(string type)
        {
            IItemManager<Item> objMgr = null;

            switch (type)
            {
                
                case "Picture":
                    objMgr = (IItemManager<Item>)new ItemManagerPictures();
                    break;

                case "Video":
                    objMgr = (IItemManager<Item>)new ItemManagerVideos();
                    break;

                default:
                    break;
            }
            return objMgr ;

        }
    }

From the controller I want to do this从控制器我想这样做

var type="Picture";

IItemManager<Item> itemMgr = ItemManagerCreator.MakeItemManager(type);
var itemList = itemMgr.FGetByGroup(string idgroup);

But I get this casting error但我得到这个铸造错误

Can't convert from type '...ItemManagerPictures' to type '...IItemManager`1[...Item]'.无法从类型“...ItemManagerPictures”转换为类型“...IItemManager`1[...Item]”。

which makes me think I'm doing something wrong, but after 1000 turns, I think the problem is with the factory method and generics, which is not well designed.这让我觉得我做错了什么,但是经过 1000 圈之后,我认为问题出在工厂方法和泛型上,它们设计得不好。

I'm new to design patterns, and maybe I'm not applying the right one.我是设计模式的新手,也许我没有应用正确的模式。

Thanks in advance提前致谢

It doesn't work as is, because ItemManagerPictures and ItemManagerVideos are indeed not convertible to IItemManager<Item> , check covariance and contravariance to see why.它不能按ItemManagerPictures工作,因为ItemManagerPicturesItemManagerVideos确实不能转换为IItemManager<Item> ,请检查协方差和逆变以了解原因。

In this case, because you actually do not need to use IList as return type of FGetByGroup (as figured out in comments), you can make it work by using some interface which is covariant in generic type T (such as IEnumerable<T> or IReadOnlyList<T> ) and then declare your type T as covariant too:在这种情况下,因为您实际上不需要使用IList作为FGetByGroup返回类型(如注释中所示),您可以通过使用一些在泛型类型T协变的接口(例如IEnumerable<T>IReadOnlyList<T> ),然后将您的类型T也声明为协变

public interface IItemManager<out T>{
    IReadOnlyList<T> FGetByGroup(string idgroup);
}

public class ItemManagerPictures : IItemManager<ItemPicture>{
    public IReadOnlyList<ItemPicture> FGetByGroup(string idgroup) {
        return null;
    }
}

Now, ItemManagerPictures is assignable to IItemManager<Item> so your code will work without exceptions.现在, ItemManagerPictures可分配给IItemManager<Item>因此您的代码将正常工作。

From your code you seem to know beforehand what type of ItemManager you want, so you can do something like this :从您的代码中,您似乎事先知道您想要什么类型的 ItemManager,因此您可以执行以下操作:

public class ItemManagerCreator
{
    public static IItemManager<T> MakeItemManager<T>() where T : Item
    {
        if (typeof(T) == typeof(ItemPicture))
        {
            return (IItemManager<T>)new ItemManagerPictures();
        }

        if (typeof(T) == typeof(ItemVideo))
        {
            return (IItemManager<T>)new ItemManagerVideos();
        }

        throw new InvalidOperationException();
    }
}

And for use :并使用:

string groupId = string.Empty;
dynamic itemManager = null;

I want an IItemManager for pictures我想要一个用于图片的IItemManager

itemManager = ItemManagerCreator.MakeItemManager<ItemPicture>();
IList<ItemPicture> pictures = itemManager.FGetByGroup(groupId);

Then I want an IItemManager for videos然后我想要一个用于视频的IItemManager

itemManager = ItemManagerCreator.MakeItemManager<ItemVideo>();
IList<ItemVideo> videos = itemManager.FGetByGroup(groupId);

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

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