• 自定义的泛型类和泛型约束


    自定义的泛型类和泛型约束

    现在继续考虑Order,在企业中订单有很多种,运输单、出库单、外借单、报关单等等。因此应该把Order作为基类,然后其他订单从该类派生。
    现在我们再看一下用户业务流程:当不同的用户角色创建了不同的订单,然后系统将这些订单汇总到公司的审计部,当审计通过后,订单将转向各自需要处理的业务部门。
    为了实现这个方案,我们在Order声明了一个Send方法。
    1    public class Order
    2    {
    3        public string OrderID;
    4        public readonly DateTime CreateDate = DateTime.Now;
    5        public virtual  void Send()
    6        {System.Console.WriteLine("Order");}
    7    }

    由于Send声明为virtual的,所以为其子类的各订单提供了多态的行为。
     1    public class ConsignationBill : Order
     2    {
     3        public override void Send()
     4        {
     5            System.Console.WriteLine("ConsignationBill");
     6        }

     7    }

     8    public class DispatchBill : Order
     9    {
    10        public override void Send()
    11        {
    12            System.Console.WriteLine("DispatchBill");
    13        }

    14    }

    15    public class WarehouseBill : Order
    16    {
    17        public override void Send()
    18        {
    19            System.Console.WriteLine("WarehouseBill");
    20        }

    21    }
    现在考虑一个很实际的处理问题,当审计部门通过了订单的审核,需要执行Send方法,以便将订单转到业务相应的部门。那我们希望有一个类来处理对审核后的订单的任务传递
     1    public class Audit
     2    {
     3        private readonly Order tmpOrder;
     4        public Audit(Order order)
     5        {
     6            tmpOrder = order;
     7        }

     8        public void AuditTask()
     9        {
    10            tmpOrder.Send();
    11        }
        
    12    }
    测试一下
    1            new Audit(new ConsignationBill()).AuditTask();
    2            new Audit(new DispatchBill()).AuditTask();
    3            new Audit(new WarehouseBill()).AuditTask();

    通过了,效果不错。
    现在考虑更多情况,Send很明显是用于业务流转的方法,除了订单,其他业务数据也会有流转的要求,为了统一,很显然,应该用到接口
    1    public interface ISend
    2    {
    3        void Send();
    4    }
    更特别的是,不是所有的单据都有业务流转的行为,所有不能让Order去实现ISend接口,而是由Order的各子类去按实际情况分别实现ISend。
    所以刚才的类的实现为
     1    public class ConsignationBill : Order,ISend
     2    {
     3        public void Send()
     4        {
     5            System.Console.WriteLine("ConsignationBill");
     6        }

     7    }

     8    public class DispatchBill : Order, ISend
     9    {
    10        public void Send()
    11        {
    12            System.Console.WriteLine("DispatchBill");
    13        }

    14    }

    15    public class WarehouseBill : Order, ISend
    16    {
    17        public void Send()
    18        {
    19            System.Console.WriteLine("WarehouseBill");
    20        }

    21    }
    现在我们如果要求Audit能够正常调用Send的方法,那Audit的实现为
     1    public class Audit
     2    {
     3        private readonly ISend sender;
     4        public Audit(ISend Sender)
     5        {
     6            sender = Sender;
     7        }

     8        public void AuditTask()
     9        {
    10            System.Console.WriteLine(sender.GetType().ToString());
    11            sender.Send();
    12        }
        
    13    }
    ok,虽然修改了Audit,但对调用者完全没有影响。那还有新的要求吗?有!
    现在Audit类能接受所有实现了ISend的类,现在要求更严谨的处理:Audit类只能处理Order的子类,且该子类必须实现了ISend的接口。
    晕啊,怎么写啊?使用反射帮忙
     1    public class Audit
     2    {
     3        private readonly ISend sender;
     4        public Audit(ISend Sender)
     5        {
     6            sender = Sender;
     7        }

     8        public void AuditTask()
     9        {
    10            if (sender.GetType().BaseType.Name == "Order")
    11            {
    12                System.Console.WriteLine(sender.GetType().BaseType.Name);
    13                System.Console.WriteLine(sender.GetType().ToString());
    14                sender.Send();
    15            }

    16        }

    17    }
    那能不能代码更简洁简单呢?可以,用泛型的约束能力
     1    public class TAudit<T> where T : Order, ISend
     2    {
     3        private readonly T sender;
     4        public TAudit(T Sender)
     5        {
     6            sender = Sender;
     7        }

     8        public void AuditTask()
     9        {
    10            System.Console.WriteLine(sender.GetType().BaseType.Name);
    11            System.Console.WriteLine(sender.GetType().ToString());
    12            sender.Send();
    13        }

    14    }

    以上说明该泛型能接受的对象是从Order继承,且实现了ISend接口,实例化的代码为
    1            new TAudit<ConsignationBill>(new ConsignationBill()).AuditTask();
    2            new TAudit<DispatchBill>(new DispatchBill()).AuditTask();
    3            new TAudit<WarehouseBill>(new WarehouseBill()).AuditTask();
    使用泛型的约束,能让代码更加的清晰和简单。
  • 相关阅读:
    常用的长度单位
    HTML常用的列表标签
    html常用文本标签
    CSS选择器及优先级
    块级元素与内联元素
    移动端app打包
    内联框架
    Leetcode303.区域和检索-数组不可变
    Leetcode107.二叉树的层次遍历||
    Leetcode784.字母大小写全排列
  • 原文地址:https://www.cnblogs.com/shyleoking/p/680043.html
Copyright © 2020-2023  润新知