如何在Winforms应用程序中使用Unity容器从BLL类实例化DAL类

罗伯特码

我试图在将Visual Studio 2015与.net 4.5.2结合使用的Winforms C#解决方案中使用Microsoft Unity容器。和实体框架6。

我有一个分层的WinForms解决方案,其中包含以下项目:

  • AppStartup(仅设置Unity容器和注册。此处没有UI)
  • UI(用户界面)
  • BLL(业务逻辑层)
  • DAL(数据访问层)

我最初是作为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。

提前致谢。

雅库布·马萨德(Yacoub Massad)

解决方案是使用构造函数注入(类似于您认为应该执行的操作)。

这是一个例子:

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在未附加到应用程序模型的类中使用eclipse 4 DI?

如何在现有应用程序中使用测试容器?

在Spring Boot应用程序中配置Spring Security时,如何在没有@Configuration的类中使用@Bean?

如何在Windows 10 C#通用应用程序中使用C ++类?

如何在WinForms客户端应用程序中使用命令模式?

如何在.NET核心应用程序中使用.NET核心类库?

如何在Xamarin应用程序中创建用于数据管理的类的实例?

Scala:如何在整个应用程序中使用Global Config案例类

在Rails应用程序中使用服务类

如何在Wildfly群应用程序中使用YAML配置自定义主类

.Net Core 2.0 Web Api:无需在BLL类中实例化dbcontext的干净方法即可调用DAL类

如何在C#应用程序中将Web服务中使用的Bitmap类转换为System.Drawing.Bitmap?

在OSGi应用程序中使用Openjfx 11类

在单元测试中实例化应用程序类

如何在Docker容器中使用Selenium设置python应用程序

如何在启动应用程序时自动创建类的单个实例

调用Application.Run()或实例化WinForms UserControl对象时,在.NET Console中使用Async / Await中断应用程序

如何在laravel应用程序中使用docker容器运行websockets

如何在Docker Compose多容器应用程序中使用GoCQL连接到bitnami / cassandra?

可以在out应用程序中使用的类

iOS创建实例并在应用程序的许多类中使用的最佳方法

无法实例化扩展应用程序类的应用程序错误

如何在WP8.1应用程序中使用Reflection获取命名空间中的所有类?

如何在IOS的其他类中使用应用程序委托的int?

使用Unity拦截应用程序中的所有类

如何从类库中的主应用程序使用dryioc容器

在应用程序中使用媒体类

如何在整个应用程序中使用PHP类,而又不影响过多的开销性能

在应用程序类中使用静态接口是否安全?