zl程序教程

您现在的位置是:首页 >  后端

当前栏目

关于DDD:管理"工作单元实例"的两种模式的使用方法

实例方法模式DDD 使用 管理 关于 工作
2023-06-13 09:14:52 时间
图如下:

在常见的用例场景下,类图的对象图如下:

问题在一个用例执行过程中,如何保证同一个界限上下文内的所有仓储实例可以共享同一个工作单元实例?解决方案1 
仓储采用依赖注入模式+使用IOC管理工作单元的生命周期(PerRequest或其它)。

代码示例

复制代码代码如下:

usingSystem;
 usingSystem.Collections.Generic;
 usingSystem.Linq;
 usingSystem.Text;
 usingSystem.Threading.Tasks;

 usingAutofac;

 namespaceAutoFacStudy
 {
    classProgram
    {
        staticvoidMain(string[]args)
        {
            varbuider=newContainerBuilder();
            buider.RegisterType<服务>();
            buider.RegisterType<仓储A>();
            buider.RegisterType<仓储B>();
            buider.RegisterType<工作单元>().InstancePerLifetimeScope();

            varcontainer=buider.Build();

            dynamic服务=container.Resolve<服务>();

            //下边两行代码输出一样
            Console.WriteLine(服务.仓储A.工作单元.GetHashCode());
            Console.WriteLine(服务.仓储B.工作单元.GetHashCode());
        }
    }

    publicclass服务
    {
        privatereadonly仓储A_仓储A;
        privatereadonly仓储B_仓储B;

        public服务(仓储A仓储A,仓储B仓储B)
        {
            _仓储A=仓储A;
            _仓储B=仓储B;
        }

        public仓储A仓储A
        {
            get{return_仓储A;}
        }

        public仓储B仓储B
        {
            get{return_仓储B;}
        }
    }

    publicclass工作单元{}

    publicclass仓储A
    {
        privatereadonly工作单元_工作单元;

        public仓储A(工作单元工作单元)
        {
            _工作单元=工作单元;
        }

        public工作单元工作单元
        {
            get{return_工作单元;}
        }
    }

    publicclass仓储B
    {
        privatereadonly工作单元_工作单元;

        public仓储B(工作单元工作单元)
        {
            _工作单元=工作单元;
        }

        public工作单元工作单元
        {
            get{return_工作单元;}
        }
    }
 }

解决方案2
仓储采用服务定位器模式+使用服务定位器或简单工厂管理工作单元的生命周期(PerRequest或其它)。
代码示例
复制代码代码如下:

usingSystem;
 usingSystem.Collections.Generic;
 usingSystem.Linq;
 usingSystem.Text;
 usingSystem.Threading.Tasks;

 usingAutofac;

 namespaceAutoFacStudy
 {
    classProgram
    {
        publicstaticIContainer服务定位器;

        staticvoidMain(string[]args)
        {
            varbuider=newContainerBuilder();
            buider.RegisterType<服务>();
            buider.RegisterType<仓储A>();
            buider.RegisterType<仓储B>();
            buider.RegisterType<工作单元>().InstancePerLifetimeScope();

            服务定位器=buider.Build();

            dynamic服务=服务定位器.Resolve<服务>();

            //下边两行代码输出一样
            Console.WriteLine(服务.仓储A.工作单元.GetHashCode());
            Console.WriteLine(服务.仓储B.工作单元.GetHashCode());
        }
    }

    publicclass服务
    {
        privatereadonly仓储A_仓储A;
        privatereadonly仓储B_仓储B;

        public服务(仓储A仓储A,仓储B仓储B)
        {
            _仓储A=仓储A;
            _仓储B=仓储B;
        }

        public仓储A仓储A
        {
            get{return_仓储A;}
        }

        public仓储B仓储B
        {
            get{return_仓储B;}
        }
    }

    publicclass工作单元{}

    publicclass仓储A
    {
        privatereadonly工作单元_工作单元;

        public仓储A()
        {
            _工作单元=Program.服务定位器.Resolve<工作单元>();
        }

        public工作单元工作单元
        {
            get{return_工作单元;}
        }
    }

    publicclass仓储B
    {
        privatereadonly工作单元_工作单元;

        public仓储B()
        {
            _工作单元=Program.服务定位器.Resolve<工作单元>();
        }

        public工作单元工作单元
        {
            get{return_工作单元;}
        }
    }
 }

由此示例可以看出,服务定位器和依赖注入可以混合在一起使用。这个例子我为了简单,服务定位器和IOC容器是同一个实例。

有些系统将服务定位器的实现换成简单工厂模式,他们本质上是一样的(服务定位器是一个万能工厂)。

代码示例

复制代码代码如下:
publicclass工作单元工厂
 {
    publicstatic工作单元创建()
    {
        var工作单元=(工作单元)CallContext.GetData("工作单元");

        if(工作单元==null)
        {
            工作单元=new工作单元();
            CallContext.SetData("工作单元",工作单元);
        }

        return工作单元;
    }
 }