【问题标题】:Best Design For Constantly Changing Property Within A Singleton Class With IoC Usage?在使用 IoC 的单例类中不断更改属性的最佳设计?
【发布时间】:2019-01-22 16:18:37
【问题描述】:

我有以下具有公共属性 _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")));

我试过在容器注册中加入sn-ps,比如一个

new InjectionProperty()

但这似乎不会在第一次实例化后更新 _variableHandler 属性。我在这里错过了一些重要的事情吗?或者尝试做一些 IoC 容器无法完成的事情?

【问题讨论】:

  • VariableHandlerFactory.GetInstance("Str") 是否返回IVariableTypeHandler 的实例?另外我认为您需要使用[Dependency] 属性注释属性...

标签: c# design-patterns inversion-of-control unity-container property-injection


【解决方案1】:

一般来说,好的设计建议使 helper\manipulator\operation 类无状态。在这里,您显然有一个有状态的辅助类,因为您可以通过属性 _variableHandler 设置对象的状态(不是真正的属性,它更像是一个字段)。

您可以做的是为IVariableHandler 制作工厂,将其注册到 IoC 中并将其注入XAMLHelper。然后在调用 helper 时,您只需指定要使用的处理程序并使用工厂重新创建它。使用某种缓存重用已经创建的对象,工厂可能会更聪明一些。

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; }

那么你可以使用InjectionProperty注册XAMLHelper

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);

【讨论】:

  • 确实,VariableHandlerFactory.GetInstance("Str") 确实返回了IVariableTypeHandler 的实例。您能否建议一种简单的方法来使XAMLHelper 类无状态但仍使用工厂生产的VariableHandlers?我还按照建议添加了“依赖”属性,然后使用此代码 container.Resolve&lt;XAMLHelper&gt;(new PropertyOverride("VariableHandler", VariableHandlerFactory.GetInstance("Int"))); 从默认的 VariableHandler 更新属性(如容器注册中所述),但它似乎没有更新属性。有什么建议吗?
  • @unknownpresense 比如为什么XAMLHelper必须是单例的,你能不能每次都创建它并注入IVariableTypeHandlerIVariableTypeHandler有多少变种,你能注册所有类型吗?
  • XAMLHelper 类在每个循环中被调用大约 100 次,并且该进程在一次运行中最多可以循环 30 次。在这 100 次调用中,VariableHandler 属性大约更新了 6 次。我认为每次创建一个新实例都会有点矫枉过正。目前IVariableHandler 有 20 种变体,但很容易增长到两倍,这就是为什么我认为工厂是合适的。我正在尝试以高标准编写代码(遵循 SOLID、DRY 等),因此任何改进都将受到高度赞赏:)
  • @unknownpresense 对于IVariableHandler,您可以拥有很好的工厂或构建器,也许工厂带有底层缓存,因此您只创建一次并在可能的情况下存储。然后将该工厂注入XAMLHelper 并通过指定使用哪个IVariableHandler 来调用XAMLHelper 上的方法......这可能吗?
  • @unknownpresense 您可以像IDictionary&lt;Type, IVariableHandler&gt; 一样简单地缓存它们。 XAMLHelper 中的那个并不是真正需要的,但也可能像 L1、L2 缓存......我应该把它也包含在答案中吗?
猜你喜欢
  • 2020-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多