D365F&O扩展类(三)

这部分内容没找到相关文档参考,只是结合在VS里debug结果猜想一下。
首先解决一个问题,扩展类是什么时候实例化的,这个很容易求证,用VS debug跟踪一下就知道了。

 1 static public void Main(Args _args)
 2     {
 3         Person person = new Person();
 4         
 5         person.Height = 1.75;
 6         person.Weight = 70;
 7 
 8         info (num2Str(person.BMI(),0 ,2, 0, 0));
 9         Person::Introduce();
10     }

执行到第5行,第一次引用到扩展类实例属性的时候会调用Person_Extension的new方法进行实例化。
如果最开始不调用实例属性,直接调用Person_Extension的实例方法会进行实例化吗?

 1 static public void Main(Args _args)
 2     {
 3         Person person = new Person();
 4         
 5         person.Stage();
 6 
 7         person.Height = 1.75;
 8         person.Weight = 70;
 9 
10         info (num2Str(person.BMI(),0 ,2, 0, 0));
11         Person::Introduce();
12     }

执行到第5行调用Stage这个实例方法的时候,并不会调用Person_Extension的new方法进行实例化。
也就是说Person这个实例对象在调用Person_Extension的实例方法的时候,Person_Extension还没实例化,正常情况下如果对象没有实例化就调用它的实例方法,会报错的。
跟踪进Stage方法,用变量跟踪查看this

 VS给出的提示是this在静态方法中无效,所以这个Stage方法虽然签名是个实例方法,但是可能只是个语法糖,实质上跟C#的扩展方法一样,是个静态方法,只不过被X++封装成了个实例方法,这样语义上好理解。

在监视器里看到一个@this的变量,它的构成是Person的类变量 + Person_Extension。

由此猜想,它的实现是不是这样:
系统在底层构造了一个对象,这个对象存放被扩展类和扩展类,就是存放了Person及其扩展类,比如Person_Extension,为了验证这个说法,再创建一个Person的扩展类Person_Another_Extension,可以看到@this里多了一个变量。

 实例化后的对象person在调用扩展类的方法时,实际上是按照C#扩展方法的方式调用的,Person_Extension的实例方法,比如Stage,实际上是静态方法,person对象在调用stage的时候,把指向person对象的引用作为方法的第一个参数隐形传给了该方法,这样才能解释为什么在Person_Extension未实例化的情况下还可以调用实例Stage方法,以及在变量追踪的时候,查看this变量会提示this在静态方法中无效。

Person_Extension实例化出来只是为了存放扩展的实例属性的值,如测试例子中的Height和Weight,只有调用到实例属性的时候才会实例化扩展类,如果扩展类没有包含实例属性,可能都扩展类都不会被实例化。
以上纯属猜想,我们使用X++的扩展类时把它当做一般的类来使用理解它的语义就可以了,至于底层的实现猜想一下只是为了满足好奇心。
D365F&O的扩展类学习到此结束。

原文地址:https://www.cnblogs.com/Farseer1215/p/12775338.html