我有两个使用以下 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)、抽象类)的具体对象。
您可以通过注册对象将用于每个抽象依赖项的类型来做到这一点。在您的示例中,当 IUnitOfWork
或 DbContext
时,将提供 MyDbContext
的实例。
因此,“声明”依赖项的项目完全独立于特定的实现。
但是,当您注册依赖类型时,您就失去了这种独立性。
让我们看一个例子:
如果我说“我渴了,我需要喝水,但我不介意我喝什么”,我会依赖任何饮料,而不是特定的饮料。但如果我说“当我口渴的时候我想喝可乐”,我就会依赖可乐。
第一部分是依赖项的抽象定义:“任何饮料”(如抽象IUnitOfWork
或DbContext
)。第二部分是具体依赖项:“可乐”(如 MyDbContext
)。
因此,只要我不指定我想喝什么,我就不会喝可口可乐。但一旦我说出来,我就会依赖。
也许您正在寻找一种在运行时更改存储库的方法。您可以这样做:不要在代码中注册依赖项,因为您需要使用所选的具体类型来引用项目。在外部配置(即文件)中执行,以便您可以在不引用依赖项的情况下编译项目,并在运行时提供所需的程序集。
注意:当我说“声明”时,我的意思是使用任何模式来注入(inject)依赖项,例如构造函数注入(inject)(最建议)或任何其他注入(inject)模式(属性依赖项)。
关于c# - 在没有 Unity.MVC 的情况下解决 Unity 依赖关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16919929/