“KG” left some comments on my last post on this topic, and I was going to reply in the comments, but I scrapped that for a whole new post.
KG’s questions:
1. Is it as simple as wrapping existing code with the COM wrappers? Do I need to be concerned with any changes of code? Like creatObject or things like that?
I would not say you simply “wrap” your current ArcGIS Server client classes into COM classes. You need to think about how to break apart your code to optimize the use of SOC side processing. You don’t really want to move everything over there. My approach has been to built utility classes exposing methods to do the low level “dirty work” involving tight loops over sets of features. I then make calls to these methods from the “client” classes (running in a web service in my case).
One issue I’m having problems with is passing non-simple or non-ArcObjects types across to the object running on the SOC – I always get serialization errors on the method call. In one case, I was trying to send a System.XmlDocument across, and it threw the same error, which really suprised me. In this case, I ended up sending the XML across as a string, and it worked. I’ve gotten around this issue for now, but I’m going to look into this a little more, as it really impacts options for creating a nice OOP design.
If anyone has this working smoothly, I’d love to hear about it – it could well be that I’m just doing something wrong. I will note that I did try creating the class I wanted to pass across as a COM class, marked up the same was as the SOC classes, and I still goe the error.
I’d also suggest that you read the stuff in Chapter 4 of the ArcGIS Server Developer book so you get the correct attributes on your class, and implement the interface etc etc. If you follow that (or the samples), you should be fine.
Correct – when converting code to run in the SOC, you need to drop all your ServerContext.CreateObject(”foo”) statements, and just create an instance of the class like you would for normal ArcObjects. Another thing to keep in mind is that you don’t need to manage lifetimes when running in the SOC, so rip out any webObject.ManageLifetime and/or Using statements. Put them in the calling code, and manage the lifetime of your SOC class.
This brings up something that I’ve been puzzling on – “the zen of object lifetime managment”.
How and where do you manage lifetime of the SOC objects you instantiate? If you have a pretty simple model, like the samples, where you have one block of code that makes simple calls into AGS for data/map etc, it’s pretty simple – manage everything right there, and call webObject.dispose at the end.
But what if you have helper classes that deal with common tasks? I’ve found that if I try to manage lifetime (within the method itself) of objects instantiated in these methods, then the objects (or pointers to objects) returned from the method are really pointing to “nothing” after webObject.dispose is called. So what’s the best plan here? I have not worked this out yet, but one idea is to pass a webObject into the methods, have it manage lifetime on the objects you create in the function , and call dispose all at once when you’re done the outermost function and releasing the context.
As noted, I have not tried this yet (I don’t want to change all my method signatures until I know this is a good way to do it). What’s odd is that I see no difference if I explicitly manage the lifetimes or not. Granted that at this point, I’m only exercising my classes through NUnit, but I’ve got my server object setup to have only one instance, and I can re-run my test blocks as many times as I want, and there does not appear to be anything hanging around in memory (at least memory usage of the SOC process does not ratchet up). Maybe this only shows up when you run a heavy load? Anyhow – this is something that I’m going to more reseach on. Of course anyone with insights please let me know (Andy? Jithen? Brian?)
2. So no VB6 is required huh? That would be great. I was looking into writing VB6 COM classes to run on the server but if I can use C# that would be better.
Yes – it’s much nicer to stick with the same environment for the entire project, and the debugging is pretty nice through .NET (not that I’ve tried DCOM debugging in VB6!)
3. How do you physically get the COM class over to the SOC from the dev machine? You mentioned that your dev box is the SOC but if it were not how would the move and reference take place
For development, make sure you’re working on the same box, or it will be a huge pain. For deployment, you need to put the dll’s on the SOC machine, and register them with COM. I have not done this yet, but I think you use regasm.exe(?). One thing that is a pain though is that you need to restart your server objects in order to recompile the assembly containing the SOC classes – ok, you only need to do this when debugging, after you have ungracefully exited the code, and left the SOC with pointers to your classes. I’ve also found that Visual Studio can spontaneously combust when trying to debug a process. Not sure why, but it restarts, and then works for a while longer. You’ll also need to stop the server objects when updating the dll’s on the server. This is very similar to using COM dll’s with classic ASP – start and stop IIS for each recompile.