28.10.2006, 16:40 | #1 |
Участник
|
Dynamics AX Geek: Storing objects in a container
Источник: http://AxGeek.spaces.live.com/Blog/c...DB13!137.entry
============== Axapta containers have a severe limitation: They don’t accept objects. Or do they? Well, not directly, but there is a way to do it: pack the contents into a container. Containers can store containers, so that will work. Let’s take an easy example first: static void Container1(Args _args) { container con, conSet; Set set = new Set(Types::String); int intValue = 42; real realValue = 1.61803; ; set.add("John"); set.add("Paul"); set.add("George"); set.add("Ringo"); print set.toString(); con = [set.pack(),intValue,realValue]; // do some processing, call methods using the container etc. [conSet,intValue,realValue] = con; set = Set::create(conSet); set.add("Yoko Ono"); print set.toString(); pause; } Now this was easy, because the set is a basic data type string and sets have a pack method. What if it was a real object? Well, we would have to implement the SysPackable interface. The interface only two methods: pack() and unpack(). For the next example I am going to create a new class TestPackable. I am going to get the class wizard to do most of the work for me. 1. Go to Tools / Development Tools / Wizards / Class Wizard. 2. Choose a name for the class, for example TestPackable, select class template “Normal”, no inheritance. Click Next. 3. From the list of interfaces select SysPackable. Click Next. 4. Select “Create all interface methods”, “Create all abstract methods”. Click Next. 5. Click Finish. That’s it. Now all we have to do is adding some functionality. void new(int _intValue, real _realValue, Set _set) { intValue = _intValue; realValue = _realValue; set = _set; } str toString() { return strfmt("%1 %2 %3",intValue,realValue,set ? set.toString() : ""); } public boolean unpack(container _packedClass) { container setContainer; int version = runbase::getVersion(_packedClass); switch (version) { case #CurrentVersion: [version,#CurrentList] = _packedClass; set = Set::create(setContainer); return true; default : return false; } return false; } public container pack() { container setContainer = set.pack(); ; return [#CurrentVersion,#CurrentList]; } public class TestPackable implements SysPackable { #define.CurrentVersion(1) #localmacro.CurrentList intValue, realValue, setContainer #endmacro int intValue; real realValue; Set set; } I am using the macro #CurrentList to define which instance variables to put in the container (the foundation was already generated by the wizard). I have also added a simple toString() method, so we can check the results are as expected. The following job is an example of how pack/unpack can be used: static void Container2(Args _args) { container con; Set set1 = new Set(Types::String); Set set2 = new Set(Types::String); int intValue = 42; real realValue = 1.61803; TestPackable testPackable1, testPackable2; ; set1.add("John"); set1.add("Paul"); set1.add("George"); set1.add("Ringo"); set2.add("Bjorn"); set2.add("Benny"); set2.add("Frida"); set2.add("Agnetha"); testPackable1 = new TestPackable(intValue,realValue,set1); print testPackable1.toString(); testPackable2 = new TestPackable(intValue,realValue,set2); print testPackable2.toString(); con = [testPackable1.pack(),testPackable2.pack()]; // do some processing, call methods using the container etc. testPackable1 = new TestPackable(0,0,null); testPackable2 = new TestPackable(0,0,null); testPackable1.unpack(conpeek(con,1)); testPackable2.unpack(conpeek(con,2)); print testPackable1.toString(); print testPackable2.toString(); pause; } The job creates two instances of TestPackable, puts them both into a container, retrieves them again and displays the contents for verification. SysPackable is implemented by some standard classes as well, Classes\Dialog is one of them. ============== Источник: http://AxGeek.spaces.live.com/Blog/c...DB13!137.entry |
|