21.09.2011, 05:12 | #1 |
Участник
|
X++: .NET Interop to X++ When X++ Runs as CIL
Источник: http://blogs.msdn.com/b/x/archive/20...ns-as-cil.aspx
============== In Microsoft Dynamics AX 2012 we have interoperability features that enable your .NET Framework C# code to call methods on AX classes and tables. We call this feature .NET interop to X++. In AX 2012 we also added the ability to run X++ code as .NET CIL. Most X++ as CIL scenarios run as services or batch jobs. For more information related to X++ code running in .NET CIL, see AX help topic on MSDN titled X++ Compiled to .NET CIL. This blog post explains the issues that can arise when these two features interact. And I show you the proper techniques for achieving error free interop when this interaction might occur. Proxies Before the interop scenarios can begin, you must use Visual Studio to automatically generate a proxy class. The proxy class represents an AX X++ class to your C# code. Proxy classes have the following characteristics:
Two Scenarios The standard scenarios begin with a call from X++ to your .NET assembly. Then in your C# code you construct an instance of a proxy class, and call methods on the proxy instance. Scenario #1: ExecuteStmt method on an AX Table In this scenario your C# program constructs an instance of a proxy to an AX table. Of course the C# proxy class for the table must have already been generated and compiled. Your C# code calls the ExecuteStmt method on the proxy instance, and obtains data from the table. The ExecuteStmt takes a string of SQL that is compiled at run time. This scenario works well when the X++ code runs in interpreted mode. X++ code to call your static C# method: str returnValue = TestClassLibrary.TestClass::TestExecuteFunction(); // X++ C# code constructs a proxy instance, and executes a query from TestTable: namespace TestClassLibrary // C# { public class TestClass { public static string TestExecuteFunction() { TestTable testTable = new TestTable(); // TestTable proxy testTable.ExecuteStmt("select firstonly * from %1"); return testTable.Name; } } } Issue: If the call from the proxy to the X++ method ExecuteStmt runs as CIL, a Microsoft.Dynamics.AX.ManagedInterop.OperationNotSupportedInILException exception is thrown. Solution: To avoid this issue, switch from calling ExecuteStmt with a string of X++ SQL, to calling a X++ method that contains direct X++ SQL statements. Further, your C# code can ascertain whether the X++ is being interpreted or is running as CIL. The MIL Session.IsILSession method ascertains whether the X++ code is running as CIL. After calling IsILSession, your C# code can branch to ExecuteStmt or direct X++ SELECT statements as appropriate. For the direct X++ SQL statement approach, you can create an X++ HelperClass class which contains a method. The method should query the AX TestTable directly by using the SELECT statement of X++. The SELECT statement is compiled at compile time. Have your C# code construct an instance of a proxy for the HelperClass. Then your C# code can call the method on the proxy instance. The following code example has a modified version of the C# method TestExecuteFunction. The modified C# code uses the option of calling the MIL IsILSession method. using MIL = Microsoft.Dynamics.AX.ManagedInterop; // C# namespace TestClassLibrary { public class TestClass { public static string TestExecuteFunction() { TestClassLibrary.TestTable testable; // TestTable is proxy of X++ table if (MIL.Session.IsILSession()) // X++ running as CIL { // Calls an X++ static method on helper class // to execute X++ code to fetch first record from TestTable. testTable = HelperClass.getTestTableFirstonly(); } else // X++ is interpreted { testTable.ExecuteStmt("select firstonly * from %1"); } return testTable.Name; } } } An alternative coding strategy would be to always code and call a HelperClass, so you would have no need to call the IsILSession method. Here is the method on the X++ class HelperClass: public static TestTable getTestTableFirstonly() // X++ { TestTable testTable; select firstOnly * from testTable; return testTable; } Note that writing the data access code in this early-bound approach in X++ provides a better experience than writing a late-bound text string in a managed source code file. The X++ editor provides IntelliSense, and the X++ compiler complains about errors early at compile time, not later at runtime. Scenario #2: MIL Methods that Create X++ Classes and Tables In this scenario your C# program constructs an instance of an AX X++ class and an AX table, by using MIL directly. This approach works when the X++ code is run by the AX interpreter. X++ code to start the scenario: TestClassLibrary.TestClass::TestSessionCurrentFunction(); // X++ The called C# code: In this C# code, MIL is used to obtain an instance of the MIL Object class, for the X++ class named XppClassName. MIL is also used to obtain an instance of the MIL Record class, for the AX table named XppTableName. Then static methods are called on the X++ class and the X++ table. using MIL = Microsoft.Dynamics.AX.ManagedInterop; // C# namespace TestClassLibrary { public class TestClass { public static void TestSessionCurrentFunction() { string sXppClassName = “XppClassName”; string sXppTableName = “XppTableName”; MIL.Session.Current.CreateObject(sXppClassName); MIL.Session.Current.CreateRecord(sXppTableName); MIL.Session.Current.CallStaticClassMethod (sXppClassName, "XppClassMethod"); MIL.Session.Current.CallStaticRecordMethod (sXppTableName, "XppTableMethod"); } } } Issue: If the X++ code that initiates the scenario is running as CIL, the code example would suffer a System.NullReferenceException exception when references are made to the MIL.Session.Current object (which is null in this case). Solution: Always use the proxy classes instead of using the MIL Session class methods. This is shown below: namespace TestClassLibrary // C# { public class TestClass { public static string TestSessionCureentFunction() { // XppTableName is a proxy class to an AX AOT table. XppTableName xppTableInstance = new XppTableName(); // XppClassName is a proxy class to an AX AOT X++ class. XppClassName xppClassInstance = new XppClassName(); XppClassName::XppClassMethod(); XppTableName::XppTableMethod(); } } } Note: The Axapta class of the Business Connector .NET is roughly analogous to the MIL Session class. Use of the Axapta class would have the same CIL-related issues as we discussed for the MIL Session class. Источник: http://blogs.msdn.com/b/x/archive/20...ns-as-cil.aspx
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору. |
|
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|