Autofac integration into Prism 4 - prism

I am swapping out the standard Unity container in Prism 4 and run into a problem when my modules are initializing. Before I used to get an IUnityContainer injected and this then allowed me to register additional types from my module all well and good.
Now I am injecting an AutoFac.IContainer and it does not have the RegisterType methods i need. They are located in the ContainerBuilder class.
So the simple question is how to I register types into my main container from within my modules as they are loaded.
Thanks
Craig

The standard Autofac way is building your modules as IModule classes, using builder.RegisterModule to load them into your container as part of the register process.
If you already have a container and need to add registrations to it, you use the ContainerBuilder again like this:
var cb = new ContainerBuilder();
cb.Register(...);
...
cb.Update(existingContainer);

Related

Register and Resolve DI containers in Prism 7 - Xamarin Forms

I'm using prism 7 for my new xamarin forms application.I have gone through this document.
I have couple of questions:
There are few DI interfaces I register after the app starts. We can use IContainerRegistry in app.xaml.cs to register but if we want to register or resolve in other pages, is there any way to get do it other that saving the IContainerRegistry and IContainerRegistry instance from app.xaml.cs and using it where ever we want?
To register a type the syntax is :
ContainerRegistry.RegisterInstance<ITextService>(new TextService());
But how can we register a singleton?
I saw few examples but I did not really understand how to do it? can anyone please show an example?
UPDATE:
To register a singleton,
The syntax seems like
containerRegistry.RegisterSingleton<ILoggerFacade, EmptyLogger>(); but if we just pass the type without creating an instance ( in this case, the instance of EmptyLogger), how can we use properly register them?
To register a type the syntax is: ContainerRegistry.RegisterInstance<ITextService>(new TextService());
this registers an instance not a type, btw, to register a type do ContainerRegistry.Register<IAnInterface, SomeImplementation>();
But how can we register a singleton?
ContainerRegistry.RegisterSingleton<ITextService, TextService>(); does this, and btw, an instance is a singleton by nature (because the di container always has to inject the one instance you registered as it cannot create new instances on its own)
is there any way to get do it other that saving the IContainerRegistry and IContainerRegistry instance from app.xaml.cs and using it where ever we want?
I recommend registering everything in one place rather than scattering registrations all over the project. But if you're determined, you can have IContainerRegistry injected anywhere and register your stuff.

Dependency Injection Android

I am not sure how to use Dependency Injection on Xamarin Android project solution. Currently my Android solution holds a reference to another class library solution. I have used Unity on my service layer and registered the container via WebApiConfig.cs.
My question is, how do i go about using Unity on Android side in order to run on start up, would be grateful if code was included. I dont want to new-up the container through main activity of Android. I want the container to register behind the process i.e. AppStart or Global asax where it does it for you for MVC apps. Is there a way to do it for Android? Also I noticed on Main Activity I am unable to create constructor. I guess this isnt possible but how do I go about holding object reference to my Class Library solution ? example that i attempted to do:
private IExample _ex;
MainActivity(IExample ex){
_ex = ex; //depedency Injection rather than newing it up
}
public void DoSomething(){
_ex.HelloWorld();
}
Is there a way to do it via Attribute ? Also for each of my layer do I need to install and create container in order to resolve current solution dependency ? or can I use container from android which would resolve all dependency in each layer as DDD architecture goes from outer to inner ?
In terms of setting up DI at startup you can create a custom Application implementation like so:
// Must include this attribute so that Android knows we want to use this as our Application implementation
[Application(Icon = "#drawable/Icon", Label = "#string/ApplicationName")]
public class MyApplication : Application
{
public override void OnCreate()
{
base.OnCreate();
// Do your DI initialization/registration here
}
}
I'm not sure exactly what you mean by not being able to create a constructor on the main activity. You can create constructors for any activity you feel like. You don't always see it though because people tend to put their initialization logic in OnCreate.

Autofac WebApi integration not working with MultiTenant Container

I am quite sure I am missing a very basic and simple thing here.
I am using Autofac and it's multitenant container as below
var builder = new ContainerBuilder();
// Registratino of modules here
var container = builder.Build();
var tenantStrategy = new AppSettingsTenantIdentifier(appSettings);
var mtc = new MultitenantContainer(tenantStrategy, container);
//Registration of tenant specific modules here
var resolver = new AutofacWebApiDependencyResolver(mtc);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
This is called from Application_Start. After above is called, I try to resolved one of the registered classes as below
var webApiConfig = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof (WebApiConfig)) as WebApiConfig;
One of the dependencies on this class is registered as InstancePerAPiRequest. At this point I get following error.
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
I am not sure how can I fix this. I Know that I can create a new lifetime scope with tag AutofacWebRequest and then resolve using that lifetime scope but that does not look right to me.
If you register something as InstancePerRequest or InstancePerApiRequest then you can't resolve it outside of a request.
If you need to resolve a dependency outside of a request lifetime (outside an actual API request), choose a different lifetime for it. InstancePerLifetimeScope is very close to InstancePerApiRequest and will work on a per-request basis, too.
But be careful: If you resolve something outside a request from the container and it is IDisposable then the object will stick around for the lifetime of the application because Autofac will hold onto it and try to dispose it for you. If you're unaware of the behavior, this can be a slow memory leak. You can read more about that on the Autofac wiki.

Use Container/DependencyResolver in other dll

I'm trying to get myself familiar with MVC3 and autofac but I've encountered small problem that I'm having trouble resolving.
I am using autofac integrated with MVC3 and all works well, pages are loading correctly, dependencies are being injected and that's cool. What's bugging me is how to use autofac's Container or MVC's DependencyResover in class library project.
I'm trying to create static class that will help me handle domain events. I simply want to be able to call the method with event parameter and everything should be handeled by this class. Here is code:
public static IContainer Container { get; set; }
public static void Raise<T>(T e) where T : IDomainEvent
{
foreach (var eventHandler in DomainEventManager.Container.Resolve<IEnumerable<EventHandlers.Handles<T>>>())
{
eventHandler.Handle(e);
}
}
As you can see it's pretty straightforward and everything would work great if it wasn't MVC approach. Some of my dependencies are registeres as InstancePerHttpRequest (NHibernate' session), while other are registered as InstancePerDependency or SingleInstance. Thus when I try to use container created in my UI project, I get exception that there is no httpRequest tag available.
How can i reuse the Container created in web project to get access to all of it's features, including InstancePerHttpRequest and httpRequest tag?
Or maybe there is other solution to my problem? I was thinking about using delegate function to obtain event handlers, but I cannot (can I?) create generic delegate that I would not need to initialize with concrete type at time of assignment.
Why I want to do this using static class is basically every entity and aggregate or service needs to be able to raise domain event. Injecting EventManager into every one of these would be troublesome and static class is exactly what would resolve all my problems.
If anyone could help me get my head around it I would be grateful.
Cheers, Pako
You shouldn't be referencing your container directly from your app code. This looks like the Service Locator anti-pattern. The correct action is to pass your objects the services they need to do their jobs, usually done through constructor parameters. BUT... if you are going to insist on depending on a global static, then at least model EventManager as a singleton, such that usage would look like:
EventManager.Current.Raise<SomeEvent>(someObject);
and then you can set EventManager.Current equal to a properly constructed instance when your app is initialized.

Register a runtime dependency in Castle Windsor

In a code I'm refactoring, I have the following situation:
void Plugin(IExternalService service)
{
var facade = new Facade(
new ExternalServiceWrapper(service),
new Dependency1(),
new Dependency2());
}
Where Dependency1 and Dependency2 are implementations of IDependency1 and IDependency2.
How can I convert this to a registration within Windsor installer? I can't seem to figure our how to pass the instance of IExternalService to the container.
EDIT I'm not in control of the Plugin's creation. I'd like to use it as a composition root to wire all the dependencies.
To register an existing instance, you can use the Instance method:
container.Register(Component.For<IExternalService>().Instance(service));

Resources