除了使用.NET Bussiness connector从C#工程访问AX的数据及方法,还可以使用Proxy Class for .NET Interop to X++功能直接将X++的类、表转化成C#的代理类,在.NET项目中使用代理类码更加直接的访问AX。相比较.NET Bussiness connector,前者使用后绑定编程模型,而Proxy class使用前绑定编程模型,在Visual studio的代码编辑窗口中可以得到相关方法的智能提示,所以在一些情况下Proxy class可以更好的替代.NET Bussiness connector。AX的Class、Table和Enum可以转化成C#类,步骤非常简单,以CustTable表为例:
首先需要创建一个C#的Class library工程,并添加到AOT,在把工程添加到AOT时Class library工程的引用中自动添加了Microsoft.Dynamics.Ax.ManagedInterop程序集,打开Application explorer,找到CustTable表,右键单击“Add to project”就可以了,在solution explorer中同时多了一个CustTable,我们是看不到其相应的代码的,但是在代码中使用它的方法及字段:
public class Class1 { public string GetCustomerPaymentMode(string accountNum, string dataAreaId) { string paymentMode = String.Empty; CustTable custTable = new CustTable(); // Search for the customer. custTable = CustTable.findByCompany(dataAreaId, accountNum); if (custTable.Found) { // Get the value for the customer's payment mode. paymentMode = custTable.PaymMode; } return paymentMode; } public bool GetCustomerCreditLimit(string accountNum, string dataAreaId) { bool hasCreditLimit = false; CustTable custTable = new CustTable(); // Search for the customer. custTable = CustTable.findByCompany(dataAreaId, accountNum); if (custTable.Found) { // Get the value for whether the customer has a credit limit. hasCreditLimit = (custTable.MandatoryCreditLimit == NoYes.No ? false : true); } return hasCreditLimit; }
这里的CustTable.findByCompany就是表CustTable的X++静态方法public static CustTable findByCompany(),在C#中我们可以很方便的直接使用它。有了这个Class library,我们可以在其他的工程中来使用它,所有的代理类内部都继承自Microsoft.Dynamics.AX.ManagedInterop.Object,因此需要在相应工程中添加对程序集Microsoft.Dynamics.AX.ManagedInterop的引用,在默认安装目录C:\Program Files (x86)\Microsoft Dynamics AX\60\Client\Bin下。和使用.NET Bussiness connector一样,由于程序集是2.0 runtime的混合模型程序集,所以需要把Class library及引用它的工程target都设为.NET Framework 3.5,或者target .NET Framework 4.0的工程中在app.config添加<startup useLegacyV2RuntimeActivationPolicy="true">。可以这样使用Class library来间接的使用CustTable的proxy class:
using (Session session = new Session()) { session.Logon(null, null, null, null); Class1 class1 = new Class1(); string accountNum = "3003"; string dataAreaId = "ceu"; string paymentMode = String.Empty; string hasCreditLimitText = String.Empty; bool hasCreditLimit; // Get the customer payment mode and credit limit. paymentMode = class1.GetCustomerPaymentMode(accountNum, dataAreaId); hasCreditLimit = class1.GetCustomerCreditLimit(accountNum, dataAreaId); hasCreditLimitText = (hasCreditLimit == false ? " and does not have" : " and has"); // Write the data to the console MessageBox.Show("Customer " + accountNum + " in company " + dataAreaId + " has a payment mode of " + paymentMode + hasCreditLimitText + " a mandatory credit limit."); }
Session类型来自于命名空间Microsoft.Dynamics.AX.ManagedInterop,可见仍然是需要首先登陆连接到AX系统才能后续操作。
对X++对象的方法还可以使用C#添加事件处理,比如X++定义一个类:
class MyClass { public void myMethod() { info("MyClass.myMethod called."); } }
使用一个X++的JOB来调用MyClass.myMethod方法:
static void callMyClass(Args _args) { MyClass myClass; myClass = new MyClass(); myClass.myMethod(); }
可以创建一个C#的类来捕捉myClass.myMethod()调用前和调用后的事件,和前面一样同样需要一个C#的Class library工程并添加到AOT,在工程中添加一个public类MyPostEventHandler来接收事件,保持MyPostEventHandler在代码编辑窗口中打开状态且编辑光标位于MyPostEventHandler的括号内,打开Application exlporer找到MyClass的myMethod方法,右键点击我们看到“Add pre-event handler”和“Add post-event handler”两个选项,这里测试“Add post-event handler”,在VS中会自动添加一些代码到MyPostEventHandler:
public class MyPostEventHandler { // Do not change the name of the event handler method. If you rename the method, the event handler will not work. [Microsoft.Dynamics.AX.ManagedInterop.XppClassDefiningEventAttribute(@"\Classes\MyClass")] static public void PostMyMethod(XppPrePostArgs args) { // Write an entry to the X++ InfoLog. Global.info("MyPostEventHandler.PostMyMethod called"); } }
这里的PostMyMethod及其特性是自动添加的,Global.info(....)则是我们调用X++的Global类的info方法来在AX的Client中在探测到myClass.myMethod方法调用后显示消息。其实VS在背后还做了很多动作,它会添加XppPrePostArgs类到我们的工程,还会在AOT的MyClass.myMethod节点下添加一个名为EventHandlerSubscription1 事件订阅,将工程的“Deploy to client”和“Deploy to server”属性都设为true。要使在C# class library中的MyPostEventHandler的PostMyMethod方法得到调用,还需要编译和部署class library,Server的默认部署路径在C:\Program Files\Microsoft Dynamics AX\60\Server\MicrosoftDynamicsAX\Bin\VSAssemblies\,如果没有启用程序集的Hot swapping,那还需要重启AOS,client的默认部署路径在C:\Users\ <YourUserName> \AppData\Local\Microsoft\Dynamics AX\VSAssemblies\,同样需要关闭再打开AX client才能使class libary dll得到调用。现在就可以在AX测试运行
callMyClass job了,得到的结果是info出来两天消息,一条来自于X++的myClass.myMethod,另外一条则来自于C#的MyPostEventHandler.PostMyMethod。
要调试C#的EventHandler有两种方法,第一种是在Visual studio中Debug attach到Ax32.exe,在AX中运行callMyClass job会自动跳转到EventHandler的断点,第二种是把c# class libarary工程的Target属性设置为client,Startup elment设置为Jobs\callMyClass,在VS中调试运行会自动Attach到AX Client并执行callMyClassJob。
可以看到微软把AX和Visual studio在.net平台上做了深度的整合,使得使用C#扩展AX功能变得更加的方便。更多内容见http://msdn.microsoft.com/en-us/library/gg879799。