自定义的泛型类和泛型约束
现在继续考虑Order,在企业中订单有很多种,运输单、出库单、外借单、报关单等等。因此应该把Order作为基类,然后其他订单从该类派生。
现在我们再看一下用户业务流程:当不同的用户角色创建了不同的订单,然后系统将这些订单汇总到公司的审计部,当审计通过后,订单将转向各自需要处理的业务部门。
为了实现这个方案,我们在Order声明了一个Send方法。
由于Send声明为virtual的,所以为其子类的各订单提供了多态的行为。
现在我们再看一下用户业务流程:当不同的用户角色创建了不同的订单,然后系统将这些订单汇总到公司的审计部,当审计通过后,订单将转向各自需要处理的业务部门。
为了实现这个方案,我们在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
}

2

3

4

5

6

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
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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
}

2

3

4

5

6

7

8

9

10

11

12

测试一下
通过了,效果不错。
1
new Audit(new ConsignationBill()).AuditTask();
2
new Audit(new DispatchBill()).AuditTask();
3
new Audit(new WarehouseBill()).AuditTask();

2

3

通过了,效果不错。
现在考虑更多情况,Send很明显是用于业务流转的方法,除了订单,其他业务数据也会有流转的要求,为了统一,很显然,应该用到接口
1
public interface ISend
2
{
3
void Send();
4
}

2

3

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
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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
}

2

3

4

5

6

7

8

9

10

11

12

13

ok,虽然修改了Audit,但对调用者完全没有影响。那还有新的要求吗?有!
现在Audit类能接受所有实现了ISend的类,现在要求更严谨的处理:Audit类只能处理Order的子类,且该子类必须实现了ISend的接口。
晕啊,怎么写啊?使用反射帮忙
现在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
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

那能不能代码更简洁简单呢?可以,用泛型的约束能力
以上说明该泛型能接受的对象是从Order继承,且实现了ISend接口,实例化的代码为
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
}

2

3

4

5

6

7

8

9

10

11

12

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();

2

3

使用泛型的约束,能让代码更加的清晰和简单。