C# Unity容器的基本使用(Unity v5.5.0)

1、通过编码方式使用Unity容器的步骤

1.准备基础业务类

CourseOrder课程订单实体类:

public class CourseOrder
    {
        public int OrderId { get; set; }
        public int CourseId { get; set; }
        public string CourseName { get; set; }
        public int CoursePrice { get; set; }
        public int SchoolId { get; set; }
        public int StudentId { get; set; }
    }

IOrderService课程订单接口:

public interface IOrderService
    {
        //提交订单
        int SubmitOrder(CourseOrder order);
        //查询订单
        List<CourseOrder> QueryOrders();
    }

OrderService课程订单实现类:

 /// <summary>
    /// 接口的实现(功能性业务)
    /// </summary>
    class OrderService : IOrderService
    {
        public List<CourseOrder> QueryOrders()
        {
            //实际项目中,在这里写具体查询任务...

            return new List<CourseOrder>()
            {
                new CourseOrder{
                CourseId = 1002,
                CourseName = ".NET高级VIP课程2",
                CoursePrice = 5501,
                SchoolId = 502103,
                StudentId = 2200229, },
            };
        }

        public int SubmitOrder(CourseOrder order)
        {
            //实际项目中,在这里写具体查询任务...

            Console.WriteLine("------------【提交订单成功】------------");

            //如果你不用AOP思想的话,你可能想到,这个地方写调用第三方支付接口完成支付等任务(如提醒业务)...

            return 1000;
        }
    }

2.添加Unity容器的引用

使用NuGet管理器添加Unity容器的引用,如下:

在这里插入图片描述

3.给基础业务添加具体的注入类

编写三个具体的注入类,都继承ICallHandler如下:

//需要引用命名空间 using Unity.Interception.PolicyInjection.Pipeline;
//需要引入命名空间 using Unity.Interception.PolicyInjection.Policies;

#region 扩展我们需要的行为类
    //数据校验类
    class DataValidateHandler : ICallHandler
    {
        public int Order { get; set; }//这个是标识注入顺序的属性

        /// <summary>
        /// 注入的行为
        /// </summary>
        /// <param name="input">输入参数</param>
        /// <param name="getNext">调用下一个行为的委托</param>
        /// <returns></returns>
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            CourseOrder order = input.Inputs[0] as CourseOrder;
            //实现验证的过程
            if (order.StudentId.ToString().Length < 6)
            {
                return input.CreateExceptionMethodReturn(new Exception("学号长度不能小于6位"));
            }
            if (order.CoursePrice < 100)
            {
                return input.CreateExceptionMethodReturn(new Exception("价格不能小于100元"));
            }
            Console.WriteLine("订单数据校验成功");

            return getNext()(input, getNext);//跳转到下一个 注入的行为,并返回结果(F12可以发现,这是一个用委托定义的委托,所以这里的写法是委托的嵌套)
        }
    }

    //缓存类
    class CacheHandler : ICallHandler
    {
        public int Order { get; set; }//这个是标识注入顺序的属性

        /// <summary>
        /// 注入的行为
        /// </summary>
        /// <param name="input">输入参数</param>
        /// <param name="getNext">调用下一个行为的委托</param>
        /// <returns></returns>
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            CourseOrder order = input.Inputs[0] as CourseOrder;
            
            //这里编写具体的过程
            Console.WriteLine("缓存写入成功");

            return getNext()(input, getNext);//跳转到下一个 注入的行为,并返回结果
        }
    }

    //日志添加类
    class WriteLogHandler : ICallHandler
    {
        public int Order { get; set; }//这个是标识注入顺序的属性

        /// <summary>
        /// 注入的行为
        /// </summary>
        /// <param name="input">输入参数</param>
        /// <param name="getNext">调用下一个行为的委托</param>
        /// <returns></returns>
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            CourseOrder order = input.Inputs[0] as CourseOrder;

            //这里编写具体的过程
            Console.WriteLine("日志写入成功");

            return getNext()(input, getNext);//跳转到下一个 注入的行为,并返回结果
        }
    }
    #endregion

4.将当前的扩展类包装为特性类

封装上一步的三个注入类为特性类,供接口使用,如下:

//需要引入命名空间 using Unity.Interception.PolicyInjection.Pipeline; 
//需要引入命名空间 using Unity.Interception.PolicyInjection.Policies;

#region 封装特性类
    public class DataValidateHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new DataValidateHandler { Order = this.Order };
        }
    }

    public class CacheHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new CacheHandler { Order = this.Order };
        }
    }

    public class WriteLogHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new WriteLogHandler { Order = this.Order };
        }
    }
    #endregion

5.给接口增加特性类

给需要切入的接口,添加特性类,如下:

/// <summary>
    /// 课程订单接口
    /// </summary>
    /// 
    [WriteLogHandler(Order = 10)]
    [DataValidateHandler(Order = 5)]
    [CacheHandler(Order = 8)]
    public interface IOrderService
    {
        //提交订单
        int SubmitOrder(CourseOrder order);
        //查询订单
        List<CourseOrder> QueryOrders();
    }

6.使用Unity容器

使用Unity容器的格式,如下:

//需要引入命名空间 
//using Unity;
//using Unity.Interception.ContainerIntegration;
//using Unity.Interception.Interceptors.InstanceInterceptors.InterfaceInterception;

class Program
    {
        static void Main(string[] args)
        {
            //【1】获取容器
            IUnityContainer container = new UnityContainer();

            //【2】注册服务
            container.RegisterType<IOrderService, OrderService>();

            //【3】注入业务
            container.AddNewExtension<Interception>().Configure<Interception>().SetInterceptorFor<IOrderService>(new InterfaceInterceptor());

            //【4】创建对象
            IOrderService orderService = container.Resolve<IOrderService>();

            //【5】业务调用
            CourseOrder order = new CourseOrder
            {
                CourseId = 1001,
                CourseName = ".NET高级VIP课程",
                CoursePrice = 3500,
                SchoolId = 502102,
                StudentId = 293400,
            };
            orderService.SubmitOrder(order);

            Console.ReadLine();
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7GEq55Tz-1578388135087)(C:\Users\cgs\AppData\Roaming\Typora\typora-user-images\image-20200104093417249.png)]

2、通过配置文件使用Unity容器

1.添加两个独立的引用(dll文件)

两个独立的引用分别是:

Microsoft.Practices.Unity.Configuration.dll

Microsoft.Practices.Unity.dll

还需要添加程序集中的:System.Configuration

2.添加业务接口和实现

同1.1(编码方式实现Unity容器的第一节)

OrderService课程订单实现类做了一点改动,如下:

/// <summary>
    /// 接口的实现(功能性业务)
    /// </summary>
    class OrderService1 : IOrderService
    {
        public List<CourseOrder> QueryOrders()
        {
            //实际项目中,在这里写具体查询任务...

            return new List<CourseOrder>()
            {
                new CourseOrder{
                CourseId = 2002,
                CourseName = ".NET高级VIP课程1",
                CoursePrice = 5501,
                SchoolId = 502103,
                StudentId = 2200229, },
            };
        }

        public int SubmitOrder(CourseOrder order)
        {
            //实际项目中,在这里写具体查询任务...

            Console.WriteLine("------------【OrderService1提交订单成功】------------");

            //如果你不用AOP思想的话,你可能想到,这个地方写调用第三方支付接口完成支付等任务(假如提醒业务)...

            return 1000;
        }
    }

    class OrderService2 : IOrderService
    {
        public List<CourseOrder> QueryOrders()
        {
            //实际项目中,在这里写具体查询任务...

            return new List<CourseOrder>()
            {
                new CourseOrder{
                CourseId = 2002,
                CourseName = ".NET高级VIP课程2",
                CoursePrice = 5501,
                SchoolId = 502103,
                StudentId = 2200229, },
            };
        }

        public int SubmitOrder(CourseOrder order)
        {
            //实际项目中,在这里写具体查询任务...

            Console.WriteLine("------------【OrderService2提交订单成功】------------");

            //如果你不用AOP思想的话,你可能想到,这个地方写调用第三方支付接口完成支付等任务(假如提醒业务)...

            return 1000;
        }
    }

3.修改配置文件进行配置

修改App.config,增加我们需要配置的节点,如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <unity>
    <!--注册业务类型-->
    <aliases>
      <add alias="IOrderService" type="xiketang.com.UnityTeach2.IOrderService,xiketang.com.UnityTeach2" />
      <add alias="OrderService1" type="xiketang.com.UnityTeach2.OrderService1,xiketang.com.UnityTeach2" />
      <add alias="OrderService2" type="xiketang.com.UnityTeach2.OrderService2,xiketang.com.UnityTeach2" />
    </aliases>
    <containers>
      <!--MyContainer是自定义的容器名称-->
      <!--type是接口名称,mapTo是注入的对象名称,name是我们要使用的名称-->
      <container name="MyContainer">
        <register type="IOrderService" mapTo="OrderService1" name="MyOrderService1" /> 
        <register type="IOrderService" mapTo="OrderService2" name="MyOrderService2" /> 
      </container>
    </containers>
  </unity>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
</configuration>

4.使用Unity容器加载配置文件

//需要引用命名空间
//using System.Configuration;
//using Microsoft.Practices.Unity.Configuration;
//using Microsoft.Practices.Unity;

class Program
    {
        static void Main(string[] args)
        {
            //【1】创建容器对象,并加载配置文件
            IUnityContainer container = new UnityContainer();
            container.LoadConfiguration("MyContainer");

            //【2】获得指定配置节点,并获得节点内部详情
            UnityConfigurationSection section = 
                (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);

            //【3】根据指定的name字符串返回对象
            IOrderService orderService = container.Resolve<IOrderService>("MyOrderService1");

            //【4】核心业务调用
            orderService.SubmitOrder(new CourseOrder());

            Console.ReadLine();
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yC0S5sMh-1578388135088)(C:\Users\cgs\AppData\Roaming\Typora\typora-user-images\image-20200104102726892.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值