c# - 在没有 Unity.MVC 的情况下解决 Unity 依赖关系

标签 c# unity-container dependency-resolver

我有两个使用以下 Unity 逻辑的项目:

container.RegisterType<IUnitOfWork, MyDbContext>(
    new HierarchicalLifetimeManager(),
    new InjectionFactory(
        c => new MyDbContext(configurationService.MySqlConnectionString)
    )
);
container.RegisterType<DbContext, MyDbContext>(
    new HierarchicalLifetimeManager()
);

第一个项目是一个使用 Unity.MVC4 的 Web 应用程序包所以有一个定制的 DependencyResolver 做一些工作 - 这完美地工作

第二个是非 Web 应用程序,因此使用普通的 Unity包实例,但在使用 MyDbContext 进行调用时出错。异常(exception)是

System.Data.Entity.Core.MetadataException: Schema specified is not valid. Errors: EntityDataModel.MyProject.ssdl(2,2) : error 0152: The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' for the 'System.Data.SqlClient' ADO.NET provider could not be loaded. Make sure the provider assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.

我已将两个项目设置为调用位于单独项目中的相同服务,试图将问题的根源隔离到第二个项目的 Unity 逻辑。我还应注意,我使用 Entity Framework 6 作为 ORM。

我的问题是我需要什么 Unity 代码才能让第二个项目正常工作,或者是否有一些我可以添加的 app.config 条目来引用 EF 程序集?

更新: 经过一些额外的工作后,我注意到如果我引用 DbContext 程序集:

  • Entity Framework
  • EntityFramework.SqlServer

在第二个项目中问题消失了。我想避免引用这些程序集,因为我的客户项目不应该对 ORM 有任何了解。

我还尝试更新连接字符串,因此我手动指定 ORM 项目的程序集(我的 EDMX 文件所在的位置),如 StackOverflow question 中所述但这没有任何区别。

metadata=res://nameOfDll/Model.csdl|res://nameOfDll/Model.ssdl|res://nameOfDll/Model.msl

最佳答案

您的做法是正确的。

使用 DI,您可以从应用程序中删除依赖项。这样您就可以获得“存储库不可知”应用程序。你已经有效地做到了。至少在“声明”依赖关系的项目上。

但是,当应用程序必须运行时,您需要指定将用于“声明的”抽象依赖项(接口(interface)、抽象类)的具体对象。

您可以通过注册对象将用于每个抽象依赖项的类型来做到这一点。在您的示例中,当 IUnitOfWorkDbContext 时,将提供 MyDbContext 的实例。

因此,“声明”依赖项的项目完全独立于特定的实现。

但是,当您注册依赖类型时,您就失去了这种独立性。

让我们看一个例子:

如果我说“我渴了,我需要喝水,但我不介意我喝什么”,我会依赖任何饮料,而不是特定的饮料。但如果我说“当我口渴的时候我想喝可乐”,我就会依赖可乐。

第一部分是依赖项的抽象定义:“任何饮料”(如抽象IUnitOfWorkDbContext)。第二部分是具体依赖项:“可乐”(​​如 MyDbContext)。

因此,只要我不指定我想喝什么,我就不会喝可口可乐。但一旦我说出来,我就会依赖。

也许您正在寻找一种在运行时更改存储库的方法。您可以这样做:不要在代码中注册依赖项,因为您需要使用所选的具体类型来引用项目。在外部配置(即文件)中执行,以便您可以在不引用依赖项的情况下编译项目,并在运行时提供所需的程序集。

注意:当我说“声明”时,我的意思是使用任何模式来注入(inject)依赖项,例如构造函数注入(inject)(最建议)或任何其他注入(inject)模式(属性依赖项)。

关于c# - 在没有 Unity.MVC 的情况下解决 Unity 依赖关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16919929/

相关文章:

c# - Asp.net mvc 4 依赖解析器

angular - 在渲染 View /模板之前等待 Angular 2 加载/解析模型

c# - 获取实体的列名

c# - 当给出开始点、结束点、速度和移动开始时间时,有没有更简单的方法来计算 2D 中的对象当前坐标?

entity-framework - Unity单例多请求访问ASP.Net MVC 5

c# - 如何使用通过依赖注入(inject)使用泛型的存储库接口(interface)?

azure - 如何使用 IoC 容器让 ASPNET WebAPI 与 Azure 辅助角色上的 Microsoft.Owin.Host.HttpListener 配合使用?

c# - PDF -Adobe 数字版

c# - EF Code First 约定允许 ICollection<T> 属性为空集合而不是 null?

c# - 如何选择已在 Microsoft Unity 注册的类型的实现