设计模式以使用实体框架 TPH 继承的 Autofac 解析依赖关系
本文关键字:Autofac 关系 依赖 继承 TPH 实体 框架 设计模式 | 更新日期: 2023-09-27 18:35:00
我在实体框架中使用TPH在我的数据库中创建了Inventory表。
public abstract class Inventory
{
public Guid Id { get; set; }
public DateTime On { get; set; }
}
public class CycleCountInventory : Inventory
{
public string Frequency { get; set; }
// and other properties
}
public class SkuGroupInventory : Inventory
{
public string SkuGroup { get; set; }
// and other properties
}
我有一个要求,可以将物品添加到库存中。但是,库存存储库的行为应因库存类型而异。我有一个服务类,其中包含对存储库的引用,如下所示:
public class InventoryService : IInventoryService
{
public bool AddItems(Inventory inventory, IList<Guid> itemsGuidList)
{
// the inventory type is only known at this point
IInventoryRepo repo = (inventory is SkuGroupInventory)
? (IInventoryRepo) new SkuGroupInventoryRepo()
: new CycleCountInventoryRepo();
return repo.PerformInventory(itemsGuidList);
}
}
目前,我正在通过手动进行检查来加载IInventoryRepo
的不同实现。这种方法存在一些问题:
1.我使用Autofac来解决所有依赖项...这种方法使我的代码难以测试
2. 随着更多类型的库存添加,我的代码将变得难以管理
是否有任何模式(抽象工厂/策略等(可用于将依赖项的解析委托回 Autofac。我相信以前有人会面对这种情况。谢谢!
您可以在此处使用工厂模式。
public interface IInventoryFactory
{
// instead of type, you could also have a discriminator on the
// inventory class, to give its specific type. (enum etc.)
IInventoryRepo CreateInventoryRepo(Type inventoryType);
}
public class MyInventoryFactory : IInventoryFactory
{
// instead of type, you could also have a discriminator on the
// inventory class, to give its specific type. (enum etc.)
public IInventoryRepo CreateInventoryRepo(Type inventoryType)
{
IInventoryRepo repo = (inventoryType == typeof(SkuGroupInventory))
? (IInventoryRepo) new SkuGroupInventoryRepo()
: new CycleCountInventoryRepo();
return repo;
}
}
public class InventoryService : IInventoryService
{
private readonly IInventoryFactory _inventoryFactory;
public InventoryService(IInventoryFactory inventoryFactory)
{
_inventoryFactory = inventoryFactory;
}
public bool AddItems(Inventory inventory, IList<Guid> itemsGuidList)
{
// create the right repo based on type of inventory.
// defer it to the factory
IInventoryRepo repo = _inventoryFactory.CreateInventoryRepo(inventory.GetType());
return repo.PerformInventory(itemsGuidList);
}
}
工厂的真正具体实现将由Autofac注入,因此请在Autofac中注册。此服务类方法现在是单元可测试的,因为您可以模拟工厂。
工厂本身是可单元测试的,因为您只需要传入适当的"库存"实例即可断言正确的具体存储库。
附言请注意,Autofac甚至不需要工厂接口/混凝土类。 它可以为您注入自动工厂。但这只是人们的偏好,即使用 Autofac 自动工厂而不是基于显式接口的工厂。无论您喜欢哪个。
此外,GetType 是稍微占用性能的调用......在生产场景中,如果你的 AddItems 方法被调用了几千次,那么 GetType 不是一个好的 FIRST 选项......很多人按如下方式解决它:
将一个名为 inventoryType 的抽象 getter 枚举添加到抽象库存类
将枚举定义值作为 CycleCount、SkuGroup 等。
使用特定类型覆盖具体子类中的枚举 getter。
一旦发生这种情况,CreateInventoryRepo 方法就可以将此枚举作为参数。
public IInventoryRepo CreateInventoryRepo(InventoryType inventoryType) { IInventoryRepo repo = (inventoryType == InventoryType.SkuGroup) ? (IInventoryRepo) new SkuGroupInventoryRepo() : new CycleCountInventoryRepo(); return repo; }