Farseer

导航

D365 FO 枚举类型construct

在D365之前,一个枚举类型对应多个子类需要实例化,通常会在construct里用switch case语句根据不同的枚举值实例化不同的子类。
这种做法的问题在于,对扩展不友好,如果枚举类型增加了新的值,想扩展,即便通过CoC扩展construct方法也是很困难的事情。
D365为了实现扩展性,针对这种场景,用了Attribute,使用扩展框架进行相应子类的实例化。
假设我们用系统里已经存在的枚举类型 Gender 性别 为例,假设我们创建一个父类Person,然后男人对应的子类是Person_Male,女人对应的子类是Person_Female。
在D365之前我们通常用如下方式实例化:

 1 public static Person construct(Gender _gender)
 2     {
 3         switch (_gender)
 4         {
 5             case Gender::Male:
 6                 return new Person_Male();
 7             case Gender::Female:
 8                 return new Person_Female();
 9             default:
10                 throw Error(Error::wrongUseOfFunction(funcName()));
11         }
12     }

在D365中要通过扩展框架进行实例化,下面说一下步骤:
1.创建一个Attribute类
该类继承自SysAttribute,并且实现SysExtensionIAttribute,方法很简单,主要是parmCacheKey方法。

 1 public class GenderAttribute extends SysAttribute implements SysExtensionIAttribute
 2 {
 3     Gender          gender;
 4     public void new(Gender _gender)
 5     {        
 6         gender = _gender;
 7     }
 8     public str parmCacheKey()
 9     {
10         return classStr(GenderAttribute)+';'+int2Str(enum2int(gender));
11     }
12     public boolean useSingleton()
13     {
14         return false;
15     }
16 }

2.在子类上增加属性

 1 [Gender(Gender::Male)]
 2 public class Person_Male extends Person
 3 {    
 4     public str fromWhere()
 5     {
 6         return "Mars";
 7     }
 8 
 9 }
10 
11 [Gender(Gender::Female)]
12 public class Person_Female extends Person
13 {    
14     public str fromWhere()
15     {
16         return "Venus";
17     }
18 
19 }

3.通过框架类SysExtensionAppClassFactory实例化并调用
入参是父类的名字和相应子类的Attribute。实现的原理很简单,通过反射找到Person的两个子类Person_Male和Person_Female,然后比对参数里的属性跟子类定义里的Attribute属性哪个能匹配,哪个能匹配就用反射实例化哪个对象并返回。
至于useSingleton方法,如果要在某次调用中需要多次实例化这个类,可以考虑使用单件模式提高效率,D365把实例化好的对象缓存在GlobalCache里。

 1 abstract public class Person
 2 {
 3     public static void main(Args _args)
 4     {
 5         Person      person;
 6 
 7         person = SysExtensionAppClassFactory::getClassFromSysAttribute(
 8                                 classStr(Person),
 9                                 new GenderAttribute(Gender::Male));
10 
11         info (person.fromWhere());
12     }
13 
14     abstract public str fromWhere(){}
15 
16 }

 

posted on 2020-05-07 22:51  佛西亚  阅读(381)  评论(0编辑  收藏  举报