我试图在将Visual Studio 2015与.net 4.5.2结合使用的Winforms C#解决方案中使用Microsoft Unity容器。和实体框架6。
我有一个分层的WinForms解决方案,其中包含以下项目:
我最初是作为WinForms应用程序创建AppStartup项目的,然后删除了所有Winform文件。AppStartup项目充当应用程序启动,其唯一目的是注册我的所有Unity容器类型,如下所示:
public class UnityFramework
{
public UnityContainer MyAppUnityContainer = null;
public UnityFramework()
{
ClassRegistrations();
}
private void ClassRegistrations()
{
MyAppUnityContainer = new UnityContainer();
MyAppUnityContainer.RegisterType<MyApp.BLL.IDepartmentDataServices,
MyApp.BLL.DepartmentDataServices>();
MyAppUnityContainer.RegisterType<MyApp.DAL.IDepartmentUnitOfWork,
MyApp.DAL.DepartmentUnitOfWork>();
}
}
为了使该注册有效,我必须添加对BLL和DAL项目的引用。
从AppStartup项目的program.cs文件中调用UnityFramework类,如下所示:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Register interfaces and concrete classes
UnityFramework aUnityFramework = new UnityFramework();
Application.Run(new MyApp.UI.FormMain());
}
}
最后一行从MyApp.UI项目中调用UI,因此我还必须添加对MyApp.UI项目的引用。基本上,AppStartup项目引用了我的解决方案中的所有其他项目。
我希望BLL有一个名为GetProductList()的服务。接口和实现如下:
// Interface defined in BLL
public interface IDepartmentDataServices
{
List<Product> GetProductList();
}
// Interface implemented in BLL
public class DepartmentDataServices : IDepartmentDataServices
{
Public List<Product> GetProductList()
{
//Note: IDepartmentUnitOfWork is defined and implemented in the DAL
IDepartmentUnitOfWork aIDepartmentUnitOfWork =
MyAppUnityContainer.Resolve<IDepartmentUnitOfWork >();
return aIDepartmentUnitOfWork.GetProductList();
}
}
这是我做错事的地方。我的问题是,定义为MyAppUnityContainer的Unity容器位于AppStartup项目中。我试图将AppStartup项目添加为对BLL项目的引用,但我不能这样做,因为它警告循环依赖项。也许我不应该使用MyAppUnityContainer在BLL中创建aIDepartmentUnitOfWork的实例?
我考虑过将它作为参数从UI传递给BLL中DepartmentDataServices具体类的构造函数,但这意味着试图在UI中实例化它,这也将导致循环依赖。
这些循环依赖项错误是由于AppStartup项目中引用了所有项目以注册MyAppUnityContainer的类型而导致的。我可以在AppStartup项目中创建DepartmentDataServices实例,并将其作为参数传递给UI项目中的启动WinForm,但是这样做将使UI无需通过BLL即可获取部门数据。
我对此尝试不满意的另一件事是,我在BLL和DAL中都没有使用DepartmentDataServices的相同类名来获取部门列表。我希望在BLL和DAL中都将服务称为DepartmentDataServices,但是在这样做时,我不知道当我向要请求的BLL寻求Unity容器时,Unity容器将如何知道要使用哪种实现它来自DAL。这就是为什么我使用部门数据服务(DepartmentDataServices)名称使用BLL,然后再次使用部门名称DepartmentUnitOfWork从DAL请求服务的原因。
我如何实现此目的,以便可以完成以下操作:我的UI将具有一个带有按钮的屏幕,当按下该按钮时,将要求BLL使用BLL中的DepartmentDataServices具体类来获取产品清单,这又将导致BLL使用DepartmentUnitOfWork的DAL实现向DAL索要产品列表。DAL将结果返回给BLL,后者又将其返回给UI。
提前致谢。
解决方案是使用构造函数注入(类似于您认为应该执行的操作)。
这是一个例子:
public class DepartmentDataServices : IDepartmentDataServices
{
private readonly IDepartmentUnitOfWork m_DepartmentUnitOfWork;
public DepartmentDataServices(IDepartmentUnitOfWork uow)
{
m_DepartmentUnitOfWork = uow;
}
Public List<Product> GetProductList()
{
return m_DepartmentUnitOfWork.GetProductList();
}
}
现在,关于循环依赖问题:在“合成根目录”中编写对象。这意味着您不构造业务层中的DAL对象,也不构造UI层中的业务层对象。取而代之的是,在“合成根目录”中构建整个对象图(来自所有层的所有对象),在本例中为AppStartup项目。
因此,UI窗体的构造IDepartmentDataServices
函数应接受对业务层类型(例如)的依赖,而业务层对象的构造函数(例如DepartmentDataServices
)应接受DAL类型的依赖(例如IDepartmentUnitOfWork
)。
这是一个如何在AppStartup项目中手动构造对象图的示例:
var uow = new DepartmentUnitOfWork(connection_string);
var service = new DepartmentDataServices(uow);
var form = MyApp.UI.FormMain(service);
Application.Run(form);
这是一个示例,说明如何在没有容器的情况下组成对象(称为Pure DI)。我用它只是为了让您了解构造函数注入的工作方式。但是您仍然可以使用DI容器。只需在“合成根目录”中在此处注册类型,然后要求DI容器解析主UI对象,然后DI容器就会知道如何自动创建所有依赖项(直到数据访问层对象)。这称为自动接线。
请注意,合成根是您应该使用DI容器的唯一位置。使用其他项目中的容器(如您的示例中)称为Service Location,被认为是反模式。
顺便说一句,对于两个类使用相同的名称没有任何问题,只要它们位于不同的命名空间中即可。就系统而言,这些类的名称完全不同。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句