创建使用泛型类型参数的类型的实例

时间:2016-10-28 09:58:15

标签: c# generics dependency-injection

我有以下示例代码。我已经创建了一个简单的例子来说明我的挑战。

我不确定这种模式的用途,因为我并不完全了解这些模式(但我很想学习)。

我有许多IItem类型的物品。这个例子是食品。

我有一个公共界面(IChef),其职责是获取制作特定项目的所有成分。我已经实现了这个界面Chef。

然后,我有一个内部接口(IKitchenHelper),用于使用泛型类型参数定义的通用项类型。内部接口的职责是准备项目。如果一个项目需要专家准备,那么我已经为该项目创建了一个实现IKitchenHelper的类,否则就有一个GeneralKitchenHelper。

Chef实现有一个私有方法,此方法需要获取相应的厨房助手,调用它的GetPreparedItems并建立所需项目所需的所有项目的列表。如果项有子项,私有方法需要递归调用自身。

我坚持如何找到合适的厨房帮手。我从一个工厂类开始,它维护了一个列表,列出了哪些类型需要厨房帮手。然后我尝试使用Activator.CreateInstance创建适当的KitchenHelper,但是我得到了一个强制转换异常,因为BeansOnToastSpecialist无法转换为IKitchenHelper。

我希望没有静态类并且可能使用DI,但我确保如何实现这一点。我之前在构造函数注入中使用过DI,但是,使用构造函数注入在这种情况下不能工作我相信Chef会需要一些不同的厨房助手。

任何帮助,建议将不胜感激。

public enum ItemType
{
    Tomatoes,
    Toast,
    NavyBeans,
    BakedBeans,
    BeansOnToast
}

public interface IItem
{
    ItemType ItemType { get; }
    List<IItem> SubItems { get; }
    bool IsPrepared { get; set; }
}

public class GeneralItem : IItem
{
    public GeneralItem(ItemType itemType)
    {
        this.ItemType = itemType;
        SubItems = new List<IItem>();
    }

    public ItemType ItemType { get; }
    public List<IItem> SubItems { get; }
    public bool IsPrepared { get; set; }
}

public class BakedBeans : IItem
{
    public BakedBeans()
    {
        SubItems = new List<IItem>
        {
            new GeneralItem(ItemType.Tomatoes),
            new GeneralItem(ItemType.NavyBeans),
        };
    }

    public ItemType ItemType => ItemType.BakedBeans;
    public List<IItem> SubItems { get; }
    public bool IsPrepared { get; set; }
}

public class BeansOnToast : IItem
{
    public BeansOnToast()
    {
        SubItems = new List<IItem>
        {
            new GeneralItem(ItemType.Toast),
            new BakedBeans()
        };
    }

    public ItemType ItemType => ItemType.BeansOnToast;
    public List<IItem> SubItems { get; }
    public bool IsPrepared { get; set; }
}

public interface IChef
{
    List<IItem> GetAllIngredients(IItem item);
}

public class Chef : IChef
{
    public List<IItem> GetAllIngredients(IItem item)
    {
        var items = new List<IItem>();

        GetIngredients(items, item);

        return items;
    }

    private static void GetIngredients(List<IItem> items, IItem item)
    {
        //get appropriate kitchen helper for the passed in item
        var myHelper = KitchenHelperDictionary.GetAppropriateHelper(item.ItemType);

        foreach (var preparedItem in myHelper.GetPreparedItems(item.ItemType))
        {
            //TODO: (ensure sub items are not already in the list)
            items.Add(preparedItem);
            if (item.SubItems.Count == 0) continue;

            //call method recursively for all the items subitems
            foreach (var itemSubItem in item.SubItems)
            {
                GetIngredients(items, itemSubItem);
            }
        }
    }
}

public static class KitchenHelperDictionary
{
    private static Dictionary<ItemType, Type> allKitchenHelpers =
        new Dictionary<ItemType, Type>
        {
            {ItemType.BakedBeans, typeof(BeansSpecialist)},
            {ItemType.BeansOnToast, typeof(BeansOnToastSpecialist)},
        };

    public static IKitchenHelper<IItem> GetAppropriateHelper(ItemType itemType)
    {
        //if item type is in the dictionary return a kitchen helper of that type
        //else return a generalist kitchen helper
    }
}

internal interface IKitchenHelper<T>  where T : IItem
{
    List<T> GetPreparedItems(ItemType itemType);
}

public class GeneralKitchenHelper : IKitchenHelper<IItem>
{
    public List<IItem> GetPreparedItems(ItemType itemType)
    {
        var items = new List<IItem>();

        var item = new GeneralItem(itemType) {IsPrepared = true};
        items.Add(item);

        return items;
    }
}

public class BeansSpecialist : IKitchenHelper<BakedBeans>
{
    public List<BakedBeans> GetPreparedItems(ItemType itemType)
    {
        var items = new List<BakedBeans>();

        var item = new BakedBeans {IsPrepared = true};
        items.Add(item);

        return items;
    }
}

public class BeansOnToastSpecialist : IKitchenHelper<BeansOnToast>
{
    public List<BeansOnToast> GetPreparedItems(ItemType itemType)
    {
        var items = new List<BeansOnToast>();

        var item = new BeansOnToast {IsPrepared = true};
        items.Add(item);

        return items;
    }
}

0 个答案:

没有答案