D365F&O扩展类(一)
AX在D365之前的版本,通过不同的层进行代码的管理和发布,不同层级的人在不同的Level上开发。
不知道其他人怎么处理的,如果做过了大量的客制化开发之后,如果有了新的RU,我是不敢打的,最多把Kernal的版本升一下,至于Application,真心不敢升级,处理冲突和合并代码是一场梦魇。
D365在云上,如果还采用这个策略,D365 Global发布了新的版本,谁也不敢直接发布。
所以D365采用了全新的Extension框架,系统层代码对修改封闭,对扩展开放(当然扩展点由系统层提供,并不是所有的都允许扩展),这样系统层进行修改以后,可以放心地发布,不用考虑代码冲突的问题。
https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/extensibility/class-extensions
这篇文章描述了X++新的语法特性,扩展。
正如文中提到的,可能augmentation 这个单词更贴切,因为Extend这个单词在X++里是有明确含义的,A继承自B,用的关键字和Java一样是extends,X++用的关键字更像Java,但是很多情况下,人们又习惯用Extension来表示扩展。
但是要明确的是,不管用哪个单词,X++ Extension不是继承的概念。
文中提到X++的扩展机制灵感来自于C#,不过X++的扩展确实青出于蓝而胜于蓝,比C#提高了很多个档,当然针对某个语言特性的优劣比较没有任何意义,每个语言都要考虑自己的适应场景。
X++是个平台语言,只用在D365 F&Os上,它增加的扩展特性是为了方便代码的客制化,不需要考虑那么多场景。C#是个通用性语言,它的更迭考虑得因素更多。
先看一下C#的扩展。
public class Person { public int Age { get; set; } }
定义一个最简单的类,只有年龄的属性,如果我们想加一个方法,定义未成年和成年,如果能修改代码,最简单加一个方法返回就好了。
public class Person { public int Age { get; set; } public string Stage() { if (Age <= 18) { return "未成年"; } else { return "成年"; } } }
然后直接调用这个方法就可以了。
如果不能直接修改这个类,在没有扩展类语法的情况下,我们可以增加一些辅助类方法。
public class Test { static void Main() { Console.WriteLine(PersonHelper.Stage(new Person() { Age = 20 })); Console.ReadLine(); } } public static class PersonHelper { public static string Stage(Person _person) { if (_person.Age <= 18) { return "未成年"; } else { return "成年"; } } } public class Person { public int Age { get; set; } }
这样也可以实现,但是总感觉调用起来不是那么方便,所以C#增加了扩展类的定义,同样的功能用扩展类可以定义成下面的样子。
public class Test { static void Main() { Console.WriteLine(new Person() { Age = 20 }.Stage()); Console.ReadLine(); } } public static class PersonHelper { public static string Stage(this Person _person) { if (_person.Age <= 18) { return "未成年"; } else { return "成年"; } } } public class Person { public int Age { get; set; } }
其实代码大体相同,都是静态类里的静态方法,只是C#编译器帮忙做了转换,调用起来像给Person增加了一个实例方法一样,是一个语法糖。
区别之处在于静态方法第一个入参用this修饰,this修饰的类型就是这个静态方法要扩展的类型。
从上面链接文章中提到的那样,X++的扩展类比C#的扩展类内容丰富很多,留在后面介绍。