Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在ASP.NET 5 DI中配置嵌套依赖项?_C#_Caching_Dependency Injection_Asp.net Core - Fatal编程技术网

C# 如何在ASP.NET 5 DI中配置嵌套依赖项?

C# 如何在ASP.NET 5 DI中配置嵌套依赖项?,c#,caching,dependency-injection,asp.net-core,C#,Caching,Dependency Injection,Asp.net Core,我想将一个存储库包装在另一个存储库中,该存储库将在内部使用传入的存储库时处理缓存。 这样,缓存逻辑就可以与存储库实现完全分离。该模式还允许我轻松地从内存缓存更改为分布式缓存,也就是说,我可以拥有使用不同缓存类型的不同缓存存储库,以便根据环境插入它们。在Azure上,我可以使用分布式缓存,但在单个服务器上,我可以使用内存缓存 public sealed class CachingFooRepository : IFooRepository { private IFooRepository

我想将一个存储库包装在另一个存储库中,该存储库将在内部使用传入的存储库时处理缓存。 这样,缓存逻辑就可以与存储库实现完全分离。该模式还允许我轻松地从内存缓存更改为分布式缓存,也就是说,我可以拥有使用不同缓存类型的不同缓存存储库,以便根据环境插入它们。在Azure上,我可以使用分布式缓存,但在单个服务器上,我可以使用内存缓存

public sealed class CachingFooRepository : IFooRepository
{
    private IFooRepository repo;
    private IMemoryCache  cache;

    public CachingFooRepository(IFooRepository implementation, IMemoryCache  cache, IFooCachingRules)
    {
        if ((implementation == null)||(implementation is CachingFooRepository))
        {
            throw new ArgumentException("you must pass in an implementation of IFooRpository");
        }
        repo = implementation;
        this.cache = cache;
    }

    public async Task<bool> Save(IFooItem foo)
    {
        // TODO throw if foo is null
        bool result = await repo.Save(user);
        string key = "Key-" + foo.Id.ToString();
        cache.Remove(key);
        return result;
    }

    public async Task<IFooItem> Fetch(int fooId)
    {
        string key = "Key-" + fooId.ToString();
        object result = cache.Get(key);
        if(result != null) { return (foo)result; }
        foo = await repo.Fetch(fooId);
        if(foo != null)
        cache.Set(key, foo);

        return foo;
    }

}
显然,当CachingFooRepository实现IFooRepository时,我必须确保IFooRepository的不同实现被传递到CachingFooRepository的构造函数中,因为它不是IFooRepository的真正实现,而是依赖于真正的实现

这个示例是简化的伪ish代码,是否缓存以及缓存的时间可以作为IFooCachingRules或IOptions之类的内容传入

因此,我的问题是,我如何重新启动服务,使依赖IFooRepository的东西获得CachingFooRepository的实例,但CachingFooRepository将获得IFooRepository的其他实现,如SqlFooRepository? 我想让其他类只依赖于IFooRepository,我不想让任何东西特别依赖于CachingFooRepository

这是可能的、可行的、好主意还是坏主意

我想将一个存储库包装到另一个将 在内部使用传入的存储库时处理缓存

您正在使用的模式有一个名称。它的名字叫:The

好主意,坏主意

使用decorator模式是一个很好的主意,因为它允许您添加功能,而无需对系统的任何现有部分进行更改。换言之,你能够坚持的

这可能吗


不,ASP.NETCore的内置DI容器中存在漏洞。您应该使用一个成熟的.NET现有DI库来实现这一点。应用decorator模式最受支持的三个库是和。

与流行的观点相反,decorator模式是使用内置容器实现的

通过使用链接答案中的扩展方法,注册装饰程序变得非常简单,如下所示:

public void ConfigureServices(IServiceCollection services)
{
    // First add the regular implementation
    services.AddSingleton<IDependency, OriginalImplementation>();

    // Wouldn't it be nice if we could do this...
    services.AddDecorator<IDependency>(
        (serviceProvider, decorated) => new DecoratorImplementation(decorated));
            
    // ...or even this?
    services.AddDecorator<IDependency, DecoratorImplementation>();
}

如果我只定义公共接口IFooRepositoryWrapper:IFooRepository,与IFooRepository相比,没有其他方法或属性,该怎么办。然后我创建一个DefaultFooRepositoryWrapper,它接受IFooRepository并将所有方法委托给它。我可以使大多数类依赖于IFooRepositoryWrapper而不是IFooRepositoryWrapper,然后我可以实现CachingFooRepositoryWrapper。我认为这应该适用于默认的DI,而不依赖于特定的实现。@JoeAudette:当然可以。然而,问题是您现在正在用自定义抽象来污染您的应用程序,并且您需要在整个应用程序中进行彻底的更改以使其正常工作。请不要那样做。请切换到一个像样的DI库;它们都是免费的,而且比内置库要好得多。我正在构建将成为开放源代码的组件,所以我不想强制我的组件的消费者使用任何特定的DI。我希望人们能够使用默认的DI或他们选择的任何DI。我的应用程序处于早期阶段,可以进行更改。有两个相同的接口嵌套包装器真的会造成污染吗?@JoeAudette:如果你正在构建一个开源工具,我甚至会更进一步,防止依赖任何类似DI容器的东西。因此,即使是ASP.NET中的内置DI容器也不行。当然,您不应该依赖内置容器的注册API,因为这迟早会对您和您的项目造成影响。我的产品将是人们可以消费的Nuget,而这些将不依赖于任何DI。但它也将被打包为一个工作应用程序,在启动集成文件中使用默认DI。那些希望以不同方式连接它的人可以使用任何DI或以他们想要的方式编写自己的集成文件,但我的工作示例将使用默认DI