枚举与di不相容的枚举类模式吗?
-
26-12-2019 - |
题
在进入di之前,我是一个使用所谓的枚举类(或头部强的枚举)的粉丝,其中枚举被转变为类,但设置为以类似的方式使用枚举。这使得逻辑能够真正属于要封装在正确的位置的特定枚举,并防止在代码库中的大量混乱。
一个例子是这里发现的 http://lostechies.com/Jimmybogard / 2008/08 / 12 / Enumeration-classes /
编辑: 这是一个类型的例子,如果我想向雇员输入一些新的东西是有问题的。由于静态变量,我不能使用容器。
public class EmployeeType : Enumeration
{
public static readonly EmployeeType Manager
= new ManagerType (0, "Manager");
public static readonly EmployeeType Servant
= new EmployeeType(1, "Servant");
public static readonly EmployeeType AssistantToTheRegionalManager
= new EmployeeType(2, "Assistant to the Regional Manager");
private EmployeeType() { }
private EmployeeType(int value, string displayName) : base(value, displayName) { }
}
public class ManagerType : EmployeeType
{
}
. 解决方案
我认为你可以使用策略模式在这里。您可以保持枚举类型或使用任何类型,而不是帮助您识别策略(我将在我的示例中使用字符串)。然后实现每个值的策略。
interface IEmployeeHandler
{
string EmployeeType { get; }
void Handle(Employee employee);
}
class ManagerHandler : IEmployeeHandler
{
public ManagerHandler()
{
EmployeeType = "Manager";
}
public string EmployeeType { get; private set; }
public void Handle(Employee employee) { }
}
class ServantHandler : IEmployeeHandler
{
public ServantHandler()
{
EmployeeType = "Servant";
}
public string EmployeeType { get; private set; }
public void Handle(Employee employee) { }
}
.
由于DI容器可以注入接口的多个实现,因此您可以编写这样的策略提供程序类:
class EmployeeStrategyProvider
{
private readonly IEmployeeHandler[] _employeeHandlers;
public EmployeeStrategyProvider(IEmployeeHandler[] employeeHandlers)
{
_employeeHandlers = employeeHandlers;
}
public IEmployeeHandler GetStrategy(string employeeType)
{
return _employeeHandlers.FirstOrDefault(item => item.EmployeeType == employeeType);
}
}
.
您可以使用此类来获取正确的策略,具体取决于员工类型。这是我用DI容器实现策略模式的方式。它可以使用一些改进,我 很乐意听到一些建议。
其他提示
我一直在使用这个模式一段时间,但从未考虑过需要将服务注入其中。但嘿,应该是可能的吗?
一个解决方案是延迟创建依赖于服务实例的任何枚举,直到它们是必需的 - 其他一切仍然看起来并像常规静态类型一样。
这是EmployeeType
类,添加了依赖于世代odicetagcode的Manager
的延迟实例化:
public class EmployeeType : Enumeration
{
public static Func<IBonusService> BonusService { private get; set; }
private static EmployeeType _manager = null;
public static EmployeeType Manager {
get
{
if (_manager == null) _manager = new ManagerType(BonusService());
return _manager;
} }
public static readonly EmployeeType Servant
= new EmployeeType(1, "Servant");
public static readonly EmployeeType AssistantToTheRegionalManager
= new EmployeeType(2, "Assistant to the Regional Manager");
private EmployeeType(int value, string displayName) :
base(value, displayName) { }
public virtual decimal BonusSize { get { return 0; } }
private class ManagerType : EmployeeType
{
private readonly IBonusService service;
public ManagerType(IBonusService service) : base(0, "Manager")
{
this.service = service;
}
public override decimal BonusSize {
get { return this.service.currentManagerBonus; } }
}
}
.
,您可以在组合root中配置依赖项:
[Test]
public void EmployeeType_Manager_HasBonusService()
{
Container container = new Container();
container.Register<IBonusService, BonusServiceStub>();
EmployeeType.BonusService = () => container.GetInstance<IBonusService>();
BonusServiceStub.constructed = false;
container.Verify();
//Verify has ensured the container can create instances of IBonusService
Assert.That(BonusServiceStub.constructed, Is.True);
EmployeeType manager = EmployeeType.Manager;
Assert.That(manager.BonusSize == 999m);
}
public class BonusServiceStub : IBonusService
{
public static bool constructed = false;
public BonusServiceStub() { constructed = true; }
public decimal currentManagerBonus { get { return 999m; } }
}
.
专门注入生成的原因,而不是世代odicetagcode,使得服务的寿命范围(以及装饰等)在组合根内管理并保持独立于消费者。
You could use a Singleton for your enum class.
不隶属于 StackOverflow