5

我有一个我一直在玩/学习的标准 .NET MVC3 存储库模式项目。这是相当标准的结构。

  • 存储库项目(具有下面提到的缓存基础设施)
  • 领域模型项目
  • 服务层项目
  • MVC 演示项目

我遇到了一个场景,我需要注入一个只有一个静态构造函数的类的私有成员,这让我对构造函数注入不走运。

有问题的类是使用我刚刚完成的 AppFabric 缓存实现的包装器。(对于那些如此倾向的人,我的实现基于 https://github.com/geersch/AppFabric

基本上我有:

  • 接口 ICacheProvider
  • 类 DefaultCacheProvider : ICacheProvider
  • 静态类缓存(利用我注入的任何实现)

静态类缓存是我想注入解析为 DefaultCacheProvider 的 ICacheProvider 的地方。

    private static readonly ICacheProvider CacheProvider;

    static Cache()
    {
        //DependencyResolver.Current.GetService<ICacheProvider>();

        //CacheProvider =
        //    (ICacheProvider)ServiceLocator.Current
        //                            .GetInstance(typeof(ICacheProvider));
    }

    public static void Add(string key, object value)
    {
        CacheProvider.Add(key, value);
    }

    public static void Add(string key, object value, TimeSpan timeout)
    {
        CacheProvider.Add(key, value, timeout);
    }

    public static object Get(string key)
    {
        return CacheProvider[key];
    }

    public static bool Remove(string key)
    {
        return CacheProvider.Remove(key);
    }

根据我所阅读的内容,这似乎是 ServiceLocator 的一个场景,但我已经看到了一些非常强烈的意见(反模式等),而且我对它的熟悉程度很低,所以我不确定可行的实施。

我在 StackOverflow 上看到了将 Cache 类设计为标准类并在 SingletonScope 中注入 ICacheProvider 的建议

kernel.Bind<ICacheProvider>().To<DefaultCacheProvider>().InSingletonScope();

但我个人更喜欢静态包装器以方便使用。

是 ServiceLocator 设置到这里的方式还是有其他明显的我不知道的东西?如果 ServiceLocator 是要走的路,是否可以与 Ninject 搭配使用?我知道 Ninject 现在具有服务定位器功能,但不确定如何实现。

感谢您提供任何信息。

4

1 回答 1

5

我认为您的方法缺少提供依赖注入的控制反转容器的本质。

根据我读过的内容,这似乎是 ServiceLocator 的一个场景,但我已经看到了一些非常强烈的意见(反模式等)

非常强烈的意见通常包括对单例模式的厌恶,或者换句话说,使用静态类来提供服务。这里的问题是Cache您编写的类与您提到的反模式相同的单例模式。

使用单例的代码是什么Cache样的?让我提出一个假设。

public class SomeClass
{
    public string GetSomeMetaData()
    {
        return Cache.Get("magicKey");
    }
}

在这种情况下,您已经抽象了 IoC 并通过使用 Singleton 避免了 DI。我会建议

public class SomeClass
{
    private readonly ICacheProvider _cacheProvider;

    public SomeClass(ICacheProvider cacheProvider)
    {
        _cacheProvider = cacheProvider;
    }

    public string GetSomeMetaData()
    {
        return _cacheProvider.Get("magicKey");
    }
}

现在,使用ICacheProvider直接发生在需要它的类中,并且可以更轻松地适应ICacheProvider实现的更改。它具有简化测试的额外好处。单例模式几乎不可能进行测试。

于 2011-04-22T02:43:10.307 回答