Static IoC bindings

Topics: Bootstrappers & IoC
Sep 11, 2013 at 1:05 PM
Edited Sep 11, 2013 at 1:10 PM
Hi,

I am required to host existing CM based application as an applet inside a container (Prism), and the container can show multiple instances of the same applet, as IoC registration is static i.e. IOC class is static, I cannot host multiple applets inside the container (the last IoC registration would overwrite the previous registration), is there anything I can do about it?


Thanks
Sep 11, 2013 at 1:33 PM
Could you elaborate a bit what you mean by 'applet'? Do you have a single bootstrapper, shared among 'applets'? Do they live in the same AppDomain? What kind of container are you using? MEF?

Before I can try to help you, I need a bit more of information, I fear...
Sep 11, 2013 at 1:49 PM
Edited Sep 11, 2013 at 1:53 PM
Hi,

I have defined one bootstrapper with overriden methods such as GetInstance etc that uses Unity for type/key resolution etc.

By applet i meant module (sorry for the misnomer), say i have a calculator module, and in the prism container multiple calculators can be hosted. As CM IoC is static, only the last registration would succeed (As modules are loaded one after the other). This gives very weird artifacts when multiple CM based modules are hosted.

I see Rob tried to answer the same here https://caliburnmicro.codeplex.com/discussions/347630 but I cannot get my head around "Determine Call Context" that he suggested especially in case of "Type" resolution.

Appreciate any pointers or sample.

Cheers
Sep 11, 2013 at 1:58 PM
Ah i misread Rob's thread I pointed earlier, the question he was trying to answer was when multiple IoC are available, in my case there is only one bootstapper/IoC but when multiple instance of the same module is loaded within the same app domain, the registration breaks.
Sep 11, 2013 at 2:25 PM
What he means there is that the IoC just wraps a container, so it would be possible to wrap multiple containers, given the ability to discriminate among them.
If a single container (or container instance) is/must be used, the same 'context' concept still holds: components should be registered and retrieved using keys that are module-dependant.

Now, if your goal is finding a way to don't touch existing application (module), I fear you're almost out of luck. Otherwise, you need to carefully design a context-aware mechanism for both registration and retrieval of components, so that every object that deals with the IoC is able to provide a unique key.

It is quite hard to help you at this point, since I have no clear idea of what kind of objects are 'conflicting', how are they registered, if they can actually be shared among modules or not... etc. Moreover, as stated above, if you can't touch the module code (you never said you can't, tho) there is probably no way to achieve what you need in a single AppDomain.
Sep 11, 2013 at 2:37 PM
Thanks

Fortunately I own the module code and can set up some ID based context, but then the type (somenamespace.someclassname) would remain the same between multiple instances right? i.e. In my bootstrapper when GetInstance(type, key) is invoked, there is no extra info to this function that can help me determine the context (the typeinfo being the same for any call), so i cannot use the ID or context info and resolve the type info from appropriate container.

Please do correct me. Thanks for your help.
Sep 11, 2013 at 3:00 PM
As long as the module is in full control of registration and retrieval , I think you don't need to modify the IoC.

Let's say you currently register an object of type T, with key "Shell" in your module. If your module is aware that he needs to generate unique keys, it can register an object of type T, with key "Shell_1", where '1' could be a value retrieved using an instance counter (increment a private static variable in the constructor of the relevant class that is registering the object, using Interlocked class to ensure thead safety). Obviously, this means that every object using the container directly is responsible for generating a proper unique key, and every object that needs the registered object have to be able to compute the key properly.

If registrations/retrievals happen just at the initialization phase in your module, you could even use a simpler approach: create a static context variable, accessible by the IoC; modify IoC methods to take into account the context when retrieving registered items; push a context in a static variable before building up a module; clear the context when module has been initialized is done. Feasible, but I would avoid it, since it meddles with IoC in a dirty way... the previous one, instead, handles everything on the module side, and is definitely cleaner... at least in my opinion.
Sep 11, 2013 at 3:18 PM
I see your point, one main issue is that I am working on a big enterprise project where there are going to host multiple modules inside the container, we'd like to use CM but would want to avoid any hacks, plus from maintenance point of view not every one would understand and appreciate the work around (though it may work). I will bring it up with the team but I highly doubt they would want to go using CM in such scenario. I would seriously miss using it.


Thanks for your help and time answering, much appreciate it.
Sep 12, 2013 at 10:28 AM
If the enterprise project is quite complex, I suppose modules have a specific interface or structure, so it would be a good idea to include the 'context' concept in them.
Another options could be to have unique modules, let the modules spawn the UI and for each UI element, instead of calling the IoC directly refer to the 'root' module.

If I am right, and you are dealing with a plugin-based system, every plugin must ensure that whatever it does does not interfere with other plugins, so it is not really a hack to use different keys for the same type of objects. It is just necessity... CM supports type/keys couples just to address this kind of scenarios.
Sep 15, 2013 at 11:01 AM
Hi BladeWise,

Thanks for your suggestion. Apparently this is not a green field project, this is a global project running for over 3-4 years and there are already 30 modules hosted in the container (some not even done by my very immediate team), we are 10+ developers across the globe and I am the one trying to sell CM. As some devs have not used CM yet, I am sure they would be reluctant to introduce the concept of "context" just so we could use CM, at present it is fine the way it is, just that I find using CM makes my life much easier.

I personally think static IoC hinders making use of CM in such scenarios. BTW there is a cool workaround suggested http://stackoverflow.com/questions/18743899/dealing-with-caliburn-micros-static-ioc/18769610 which i believe would work for most scenarios, but apparently not in my case as we Child Containers.

Thanks