【问题标题】:How to implement multi dependency injection decorator with autofac如何使用 autofac 实现多依赖注入装饰器
【发布时间】:2015-10-31 20:03:37
【问题描述】:

我想用 IOC 容器 autofac 调用 MessageStore 类。

如何在最新版本的 autofac 中注册这个装饰器和复合模式?

这段代码结合了复合和装饰器模式,注意SOLID Principal。

我对此感到困惑。我的问题是,这段代码如何用 autofac 定义

var fileStore = new FileStore(new DirectoryInfo(HostingEnvironment.MapPath("~/file"))); var cacheStore = new CacheStore(fileStore, fileStore); var logStore = new LogStore(cacheStore, cacheStore); var messageStore = new MessageStore(logStore, logStore); messageStore.Save(12, "Hello");

public class FileStore :  IFileLocator, IStoreWriter,IStoreReader
{
    private readonly DirectoryInfo _workingDirectory;

    public FileStore(DirectoryInfo workDirectory)
    {
        if (workDirectory == null)
            throw new ArgumentNullException("workDirectory");

        if (!workDirectory.Exists)
            throw new ArgumentException("Directory not found", "workDirectory");

        _workingDirectory = workDirectory;
    }

    public virtual void Save(int id, string message)
    {
        var path = GetFileInfo(id).FullName;
        File.WriteAllText(path, message);
    }

    public virtual Maybe<string> Read(int id)
    {
        var file = GetFileInfo(id);

        if (!file.Exists)
            return new Maybe<string>();

        var path = file.FullName;
        return new Maybe<string>(File.ReadAllText(path));
    }

    public virtual FileInfo GetFileInfo(int id)
    {
        return new FileInfo(
            Path.Combine(_workingDirectory.FullName, id + ".txt"));
    }
}

public class CacheStore : IStoreWriter, IStoreReader
{
    private readonly ConcurrentDictionary<int, Maybe<string>> _cache;
    private readonly IStoreWriter _writer;
    private readonly IStoreReader _reader;

    public CacheStore(IStoreWriter writer, IStoreReader reader)
    {
        _cache = new ConcurrentDictionary<int, Maybe<string>>();
        _writer = writer;
        _reader = reader;
    }

    public virtual void Save(int id, string message)
    {
        _writer.Save(id, message);
        var m = new Maybe<string>(message);
        _cache.AddOrUpdate(id, m, (i, s) => m);
    }

    public virtual Maybe<string> Read(int id)
    {
        Maybe<string> retVal;
        if (_cache.TryGetValue(id, out retVal))
            return retVal;

        retVal = _reader.Read(id);
        if (retVal.Any())
            _cache.AddOrUpdate(id, retVal, (i, s) => retVal);
        return retVal;
    }
}

public class LogStore :  IStoreWriter, IStoreReader
{
    private readonly IStoreWriter _writer;
    private readonly IStoreReader _reader;
    public LogStore(IStoreWriter writer, IStoreReader reader)
    {
        _writer = writer;
        _reader = reader;
    }
    public void Save(int id, string message)
    {
        Log.Information("Saving message {id}.", id);
        _writer.Save(id, message);
        Log.Information("Saved message {id}.", id);
    }

    public Maybe<string> Read(int id)
    {
        Log.Debug("Reading message {id}.", id);
        var retVal = _reader.Read(id);
        if (retVal.Any())
            Log.Debug("Returning message {id}.", id);
        else
            Log.Debug("No message {id} found.", id);
        return retVal;
    }

}

 public class MessageStore
{
    private readonly IStoreWriter _writer;
    private readonly IStoreReader _reader;
    public MessageStore(IStoreWriter writer, IStoreReader reader)
    {
        if (writer == null)
            throw new ArgumentNullException("writer");
        if (reader == null)
            throw new ArgumentNullException("reader");
        _writer = writer;
        _reader = reader;
    }

    public void Save(int id, string message)
    {
        _writer.Save(id, message);
    }

    public Maybe<string> Read(int id)
    {
        return _reader.Read(id);
    }
}

【问题讨论】:

  • 您是否尝试过自己实现此功能?你被什么困住了?在 Autofac 文档站点 (docs.autofac.org/en/latest/advanced/adapters-decorators.html) 和这篇博文 (nblumhardt.com/2010/04/…) 上有一些关于装饰器的好信息。我也认为你需要更清楚你想要达到的目标。
  • 我不知道。但我对此感到困惑。我的问题是,这段代码如何用 autofac var fileStore = new FileStore(new DirectoryInfo(HostingEnvironment.MapPath("~/file"))); var cacheStore = new CacheStore(fileStore, fileStore); var logStore = new LogStore(cacheStore, cacheStore); var messageStore = new MessageStore(logStore, logStore); messageStore.Save(12, "Hello"); 定义
  • 您能否更新您的问题以包含此信息,而不是将其作为评论留在此处?这将有助于了解实际询问的内容。

标签: c# decorator autofac composite


【解决方案1】:

鉴于您的所有商店都实现并使用IStoreReaderIStoreWriter,您可以通过将它们组合成一个IStore 接口来简化事情。这可以是定义SaveRead 方法的单个接口,也可以根据需要从现有的IStoreReaderIStoreWriter 接口继承。

然后您可以将您的FileStore(这似乎是主要实现)注册为密钥服务。然后使用RegisterDecorator 注册缓存和日志装饰器。最后注册MessageStore,解析没有key的服务,就是最外层的装饰器。

builder.Register(f => new FileStore(new DirectoryInfo(HostingEnvironment.MapPath("~/file"))))
    .Keyed<IStore>("file");

builder.RegisterDecorator<IStore>(
    (c, inner) => new CacheStore(inner), fromKey: "file", toKey: "cache");

builder.RegisterDecorator<IStore>(
    (c, inner) => new LogStore(inner), fromKey: "cache", toKey: null);

builder.Register(c => new MessageStore(c.Resolve<IStore>()));

我确信围绕装饰器的 API 可以改进,这绝对是我打算很快做的事情。

【讨论】:

    【解决方案2】:

    谢谢亚历克斯。但我用下面的代码解决了,因为我不想创建IStore。你觉得我的讨论吗?

    builder.Register(f => new FileStore(new DirectoryInfo(HostingEnvironment.MapPath("~/file")))) 
                .Named<IStoreWriter>("F-writer").Named<IStoreReader>("F-reader");
            builder.Register( 
                c => new CacheStore(c.ResolveNamed<IStoreWriter>("F-writer"), c.ResolveNamed<IStoreReader>("F-reader"))) 
                .Named<IStoreWriter>("C-writer").Named<IStoreReader>("C-reader"); 
    
            builder.Register( 
                c => new LogStore(c.ResolveNamed<IStoreWriter>("C-writer"), c.ResolveNamed<IStoreReader>("C-reader"))) 
                .Named<IStoreWriter>("L-writer").Named<IStoreReader>("L-reader"); 
    
            builder.Register( 
                c => 
                    new MessageStore(c.ResolveNamed<IStoreWriter>("L-writer"), c.ResolveNamed<IStoreReader>("L-reader")));
    

    【讨论】:

      猜你喜欢
      • 2015-09-03
      • 2014-11-10
      • 2019-11-24
      • 1970-01-01
      • 1970-01-01
      • 2018-08-07
      • 2016-08-03
      • 1970-01-01
      • 2023-03-14
      相关资源
      最近更新 更多