Unity doesn't register DomainClient?

Topics: Prism v4 - Silverlight 4
Feb 4, 2011 at 12:47 PM
Edited Feb 4, 2011 at 1:07 PM

Dear All,

 

I am a bit stuck with this. I have introduced a new paremeter in a ctor of my NavigationViewModel.  Now Prism can't resolve the parameter any more. And I get this error message:

Microsoft JScript runtime error: Unhandled Error in Silverlight Application An exception occurred while initializing module 'NavigationModule'.     - The exception message was: Activation error occured while trying to get instance of type NavigationModule, key ''    Check the InnerException property of the exception for more information. If the exception occurred     while creating an object in a DI container, you can exception.GetRootException() to help locate the     root cause of the problem.    at Microsoft.Practices.Prism.Modularity.ModuleInitializer.HandleModuleInitializationError(ModuleInfo moduleInfo, String assemblyName, Exception exception)   at Microsoft.Practices.Prism.Modularity.ModuleInitializer.Initialize(ModuleInfo moduleInfo)   at Microsoft.Practices.Prism.Modularity.ModuleManager.LoadModulesThatAreReadyForLoad()

My navigationModule has the ctor like this:

 

public NavigationModule(IUnityContainer container, IRegionManager regionManager)
        {
            _container = container;
            _regionManager = regionManager;
            
//Atempt to register DomainClient, which doesn't seem to work.
_container.RegisterType<DomainClient>(new ContainerControlledLifetimeManager());
            _regionManager.RegisterViewWithRegion(Constants.NavRegion, () => _container.Resolve<NavigationView>());
            _regionManager.RegisterViewWithRegion(Constants.ToolbarRegion, () => _container.Resolve<ToolbarView>());
        }

 

 

Navigation View Model owns by Navigation View looks simply like this:

public NavigationViewModel(DomainClient client)
        {
            _context = new SCMDomainContext(client);
            ConstructCommon();
        }

 

 

I suspect the problem is that DomainClient is an abstract class from RIA Services and the IoC can't create an instance of this abstract class, hence the error correct?
In this case, I would be happy if I could force it to ignore the ctor with the abstract DomainClient parameter, and rather try to resolve a different ctor with the non-abstract SCMDomainContext like this:

 

public NavigationViewModel(SCMDomainContext context)
        {
            _context = context;
            ConstructCommon();
        }

 

1) How would I do that in Unity?

2) Problem with MEF is that it needs an export attribute, but even the non-abstract SCMDomainContext is auto generated code by RIA services. I couldn't just go there and add an [Export] attribute on top of it? And how would I do this with MEF? 


UPDATE:
I tried to use this to select the correct ctor for injection, but it failed.

 _container.Configure<InjectedMembers>().ConfigureInjectionFor<NavigationViewModel>(new InjectionConstructor(_container.Resolve<SCMDomainContext>()));
            _container.RegisterType<SCMDomainContext>(new ContainerControlledLifetimeManager());

Besides the Injectedmember is obsolete anyway, I wondr how I have to do it nowadays. :)
I got frustrated and removed the ctor with the abstract class injection temporarily all together so that only one ctor with SCMDomainContext can be injected in. But it can't even resolve the non-abstract SCMDomainContext, which is auto generated code by RIA.

Arrgh

Your help on this is highly appreciated,
Houman 

Feb 9, 2011 at 6:22 PM

Hi Houman,

Take into account that Unity only resolve instances of concrete classes. Since your DomainClient is an abstract class, that is the cause of your error when trying to register on the container, in the NavigationModule.

One possible way to achieve this scenario, could be to register a DomainClient instance in the container on your module. For example:

//retrieve your DomainClient and create the instance of it, named client...
ConcreteClient concreteClient = client;
_container.RegisterInstance(concreteClient, new ContainerControlledLifetimeManager());//by doing this you always are going to retrieve the same instance
           ...
public NavigationViewModel(ConcreteClient client){…}

 

This way your view model will resolve you client instance and then setup the SCMDomainContext.

Take into account, that you could do the same using MEF, by just simple decorate your concrete classes.

I hope you find this information useful.

Thanks,

Miguel Bronzovic
http://blogs.southworks.net/mbronzovic