Лучший дизайн для постоянно меняющегося свойства в классе Singleton с использованием IoC? - PullRequest
0 голосов
/ 22 января 2019

У меня есть следующий вспомогательный класс с открытым свойством _variableHandler. Свойство является общедоступным, поскольку у меня изначально были видения установки свойства из вызывающего кода, прежде чем задействовать методы в классе XAMLHelper, но теперь сомневаюсь, что это разумный подход. Главным образом потому, что мне нужно будет вызывать класс довольно часто и не всегда обновлять значение _variableHandler, что означает, что все станет грязно.

public class XAMLHelper
{
    public IVariableTypeHandler _variableHandler;

    public XAMLHelper()
    {
    }
}

У меня также есть фабрика, которая используется для предоставления желаемого конкретного экземпляра VariableTypeHandler.

Я также использую контейнер IoC (Unity) для предоставления одного экземпляра класса XAMLHelper, как показано ниже.

container.RegisterInstance<XAMLHelper>(new XAMLHelper());

В идеале, я хотел бы сохранить этот единственный экземпляр, но просто обновить значение _variableHandler, когда оно указано с использованием кода, приведенного ниже.

container.Resolve(new PropertyInjection(VariableHandlerFactory.GetInstance("Str")));

Я попытался добавить фрагменты в регистрацию контейнера, например

new InjectionProperty()

Но, похоже, это не обновляет свойство _variableHandler, как только оно было создано в первый раз. Я что-то упустил здесь? Или пытаетесь сделать что-то, что невозможно с контейнером IoC?

1 Ответ

0 голосов
/ 23 января 2019

Вообще, хороший дизайн предлагает сделать помощник \ манипулятор \ операция классы без сохранения состояния. Здесь у вас явно есть вспомогательный класс с состоянием, так как вы можете установить состояние объекта через свойство _variableHandler (не реальное свойство, оно больше похоже на поле).

Что вы можете сделать, это сделать фабрику для IVariableHandler, зарегистрировать ее в IoC и ввести ее в XAMLHelper. Затем при вызове помощника вы просто указываете, какой обработчик использовать, и воссоздаете его с фабрикой. Фабрика могла бы быть немного умнее, чтобы повторно использовать уже созданный объект, используя некоторое кэширование.

public intefrace IVariableHandlerFactory
{
    IVariableHandler Get(string description);
}

public class VariableHandlerFactory : IVariableHandlerFactory
{
    private readonly IDictionary<string, IVariableHandler> _cache;

    public VariableHandlerFactory()
    {
        _cache = new Dictionary<string, IVariableHandler>();
    }

    public IVariableHandler Get(string description)
    {
        IVariableHandler handler; 

        if(_cache.TryGetValue(description, out handler))
        {
            return handler;         
        }

        handler = //create it...
        _cache[description] = handler;

        return handler;
    }
}

, а затем используйте это в XAMLHelper

public class XAMLHelper
{
    private readonly IVariableHandlerFactory _factory;

    public XAMLHelper(IVariableHandlerFactory factory)
    {
        _factory = factory;
    }

    public void HelpMe(string description)
    {
        var handler = _factory.Get(description);

        //do actual work using handler
    }
}

Давайте отложим это в сторону и обсудим реальную проблему здесь. Во-первых, вам не хватает аннотации вашей недвижимости:

[Dependency]
public IVariableTypeHandler VariableHandler { get; set; }

тогда вы можете зарегистрировать XAMLHelper, используя InjectionProperty

container.RegisterType<VariableTypeHandlerImpl, IVariableTypeHandler>();

using(var lifetime = new ContainerControlledLifetimeManager())
    container.RegisterType<XAMLHelper>(lifetime, new InjectionProperty("VariableHandler");

или, если у вас есть конкретный экземпляр IVariableTypeHandler, вы можете использовать:

var variableHandler = VariableHandlerFactory.GetInstance("Str");

using(var lifetime = new ContainerControlledLifetimeManager())
    container.RegisterType<XAMLHelper>(lifetime, new InjectionProperty("VariableHandler", variableHandler);
...