【问题标题】:Resolve generic service解决通用服务
【发布时间】:2010-10-04 19:15:01
【问题描述】:

我得到了以下服务:

IRepository<TEntity, TPrimaryKey>

..为此我创建了一个定义为:

Repository<TEntity, TPrimaryKey>.

如何在 autofac 中注册它以便我可以将其解析为:

IRepository<User, int>

【问题讨论】:

    标签: .net dependency-injection ioc-container generics autofac


    【解决方案1】:
    builder.RegisterGeneric(typeof (Repository<,>)).As(typeof (IRepository<,>));
    

    我喜欢 autofac。

    【讨论】:

      【解决方案2】:

      作为您自己的解决方案的替代方案,您可以尝试定义一个工厂来创建新的存储库实例:

      public interface IRepositoryFactory
      {
          IRepository<TEntity, TPrimaryKey> 
              CreateRepository<TEntity, TPrimaryKey>();
      
          // Perhaps other overloads here
      }
      
      internal class RepositoryFactory : IRepositoryFactory
      {
          public IContainer Container { get; set; }
      
          public IRepository<TEntity, TPrimaryKey> 
              CreateRepository<TEntity, TPrimaryKey>()
          {
              return container.Resolve<Repository<TEntity, TPrimaryKey>>();
          }
      }
      

      您可以按如下方式注册RepositoryFactory

      builder.Register(c => new RepositoryFactory() { Container = c })
          .As<IRepositoryFactory>()
          .SingleInstance();
      

      现在您可以将IRepositoryFactory 声明为构造函数参数并创建新实例。看看这个使用依赖注入的ProcessUserAccountUpgradeCommand 类的例子:

      public ProcessUserAccountUpgradeCommand : ServiceCommand
      {
          private readonly IRepositoryFactory factory;
      
          ProcessUserAccountUpgradeCommand(IRepositoryFactory factory)
          {
              this.factory = factory;
          }
      
          protected override void ExecuteInternal()
          {
              // Just call the factory to get a repository.
              var repository = this.factory.CreateRepository<User, int>();
      
              User user = repository.GetByKey(5);
          }
      }
      

      虽然使用工厂而不是直接获取存储库可能看起来有点麻烦,但您的设计将清楚地传达检索到新实例的信息(因为您调用了CreateRepository 方法)。从 IoC 容器返回的实例通常是 expected to have a long life

      另一个提示:您可能想要重构主键类型的使用。总是要求&lt;User, int&gt; 的存储库而不仅仅是&lt;User&gt; 存储库会很麻烦。也许你找到了一种方法来抽象出工厂内部的主键。

      我希望这会有所帮助。

      【讨论】:

      • 我不同意。服务不必长期存在。获取服务的代码不应该关心生命周期,它是一个实现细节。使用工厂意味着生命周期永远不会改变(因为它意味着每次都应该返回一个新实例)。例如,可以从每次从容器返回一个新实例开始,但稍后切换到单例以便能够在存储库中缓存对象。
      • 我喜欢引用 Mark Seeman 的话:“使用构造函数注入注入的依赖项往往是长期存在的,但有时您需要一个短期对象,或者基于仅在运行。” “如果您需要一个短暂的对象,请使用抽象工厂”。见:stackoverflow.com/questions/2045904/…
      • 恕我直言,它仍然不是一个有效的论点,因为它是一个实现细节。当然。如果我想获得一个用户,它不应该由 DI 创建。但是存储库是一种服务,应该被视为一种服务。大多数存储库使用具有更长生命周期的 UnitOfWork(例如在 HTTP 请求期间)
      • 请注意,最终仍在创建它们的是容器(如您在我的示例中所见)。我发现工厂更清晰,但这当然只是一种做事方式;-)
      猜你喜欢
      • 2015-01-15
      • 2011-07-09
      • 1970-01-01
      • 1970-01-01
      • 2013-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-01
      相关资源
      最近更新 更多