Участок класса Enum несовместим с ди?
-
26-12-2019 - |
Вопрос
Перед получением дие я был вполне поклонником использования так называемого класса ENUM (или сильный enum в моей голове), где перечисления превращаются в классы, но установленные для использования аналогичным образом.Это позволяет логике, которая действительно принадлежит к определенному Enum, чтобы заключаться в правильном месте и предотвращает множество беспорядков в базе кода.
Пример, который находится, который находится здесь http://lostechies.com/Jimmybogard / 2008/08 / 12 / классы перечисления /
Есть ли способ продолжать поддерживать этот шаблон, а также использовать ди?
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
{
}
. Решение
Я думаю, что вы можете использовать Стратегический паттерн здесь.Вы можете сохранить свой тип Enum или использовать любой тип, чем может помочь вам определить стратегию (я буду использовать строку в моем примере).Затем реализуйте стратегию для каждого значения.
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);
}
}
.
Вы можете использовать этот класс, чтобы получить правильную стратегию в зависимости от типа сотрудника.Вот как я реализую стратегическую узор с ди-контейнерами.Это может использовать некоторые улучшения, хотя я будет рад услышать некоторые предложения.
Другие советы
Я уже некоторое время использую этот шаблон, но никогда не учитывал необходимость ввести в нее услугу.Но эй, должно быть возможно, верно?
Одним из решений - отложить создание любых перечислений, которые зависят от экземпляра обслуживания, пока они не будут необходимы - все остальное все еще выглядит и действует как обычный статический тип.
Вот класс EmployeeType
с добавлением задержки создаваемого генеракодицетагкода, который зависит от генеракодицетагкода:
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; } }
}
}
.
и вы настраиваете зависимости в корне композиции:
[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; } }
}
.
Причина специально впрыскивая генеракодицетагкод вместо генеракодицетагкода, заключается в том, что срока службы (а также оформление и т. Д.) Управляется в корневой композиции и остается независимым от потребителя.
You could use a Singleton for your enum class.