【问题标题】:Unity IoC resolving a Generic Service plus Generic repositoryUnity IoC 解析通用服务和通用存储库
【发布时间】:2012-06-14 10:49:32
【问题描述】:

当使用 ASP.NET MVC 和实体框架,并尝试实现通用存储库和通用服务,并通过 Unity Ioc 解决所有问题时:

我正在尝试让 Unity Ioc 使用参数注入将通用服务注入控制器,但类型解析失败并出现以下错误消息:

尝试获取类型实例时发生激活错误 ISupplierService 当前构建操作(构建键 Build 键[MyApp.Services.Implementation.SupplierService, null]) 失败: 尝试获取类型实例时发生激活错误 IGenericRepository1, key \"\" Resolution of the dependency failed: The current type, MyApp.Repository.Interfaces.IGenericRepository1[Entities.Supplier], 是一个接口,不能被构造。你错过了一个类型 映射? (策略类型 BuildPlanStrategy,索引 3)

我可以理解错误消息意味着它正在尝试创建 IGenericRepository 的实例,而我实际上是在尝试让它创建 SupplierService 的实例,但我不明白为什么它会以这种方式解决。根据最初的答案,这可能是因为类型未注册

控制器的服务注入为:

public class SupplierController : Controller
{
    private readonly ISupplierService _service;
    public SupplierController() : this (null) { }
    public SupplierController(ISupplierService service) 
    {
        _service = service; 
    }
    // .. injection fails, service is NULL
}

供应商服务是一个空接口加空类(如果需要,以后可以添加自定义方法)

public partial interface ISupplierService : IGenericService<Supplier> {}  

IGenericService 只是重新呈现 IGenericRepository 的方法:

public interface IGenericService<T> : IDisposable where T : BaseEntity {}

在 Global.asax.cs 中,IoC 容器由

创建
var container = new UnityContainer();
var uri = new Uri(Assembly.GetExecutingAssembly().CodeBase);
string path = System.IO.Path.GetDirectoryName(uri.AbsolutePath);
var assemblyPaths = new List<string> 
{
    Path.Combine(path, "MyApp.Repository.Interfaces.dll"),
    Path.Combine(path, "MyApp.Repository.Implementation.dll"),
    Path.Combine(path, "MyApp.Services.Interfaces.dll"),
    Path.Combine(path, "MyApp.Services.Implementation.dll")
};

container
    .ConfigureAutoRegistration()
    .LoadAssembliesFrom(assemblyPaths)
    .ExcludeSystemAssemblies()
    .Include(If.Any, Then.Register())
    .ApplyAutoRegistration();

var serviceLocator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => serviceLocator);

【问题讨论】:

  • 你能显示你的容器的设置代码吗?
  • 您的 SupplierController 中还有其他 ctors 吗?
  • @SebastianWeber 更新了容器代码

标签: c# entity-framework dependency-injection unity-container repository-pattern


【解决方案1】:

在最新版本仍然“新鲜”时使用 UnityAutoRegistration 进行了实验,我对此并不满意。 TecX project on codeplex 包含 StructureMap 配置引擎的一个端口,它为您提供对可以让您的生活更轻松的约定的支持。

类似

ConfigurationBuilder builder = new ConfigurationBuilder();
builder.Scan(s =>
{
  s.AssembliesFromApplicationBaseDirectory();
  s.With(new ImplementsIInterfaceNameConvention());
}
var container = new UnityContainer();
container.AddExtension(builder);
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<>));
var serviceLocator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => serviceLocator);

应该注册所有的接口/服务和接口/存储库对。约定将SupplierService 注册为ISupplierService 等的实现。 使用两个开放的泛型类型(IGenericRepositoy&lt;&gt;GenericRepository)对RegisterType 的附加调用将您的泛型存储库接口映射到通用存储库类。 Unity 会自动为您关闭类型定义(即IGenericRepository&lt;Supplier&gt; 将映射到GenericRepository&lt;Supplier&gt;)。

【讨论】:

  • 谢谢,我现在正在阅读那个链接项目。当他们说“这使得容器的配置相当冗长”时。 (指unity),verbose配置方法是什么?
  • @JK 您必须为每个服务手动添加映射接口 -> 服务。 container.RegisterType&lt;ISupplierService, SupplierService&gt;(); container.RegisterType&lt;ICustomerService, CustomerService&gt;(); 等等。
  • +1 手动添加container.RegisterType&lt;ISupplierService, SupplierService&gt;(); 等已解决问题,谢谢。我会查看您建议的 codeproject 配置引擎,因为 .ConfigureAutoRegistration().ApplyAutoRegistration() 似乎没有按预期工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多