protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
referring to the above code in Prism/blob/master/Sandbox/Wpf/HelloWorld/HelloWorld/App.xaml.cs, I do not understand how the MainWindow type is registered with the container.
looking at the registrations of the container, MainWindow type is not listed.
Can someone please help me to understand how it works?
I do not understand how the MainWindow type is registered with the container
It is not registered with the container. Unity by default resolves concrete types transiently. You only have to register a concrete type if you want it to have a non-standard lifetime, e.g. a singleton.
Related
I'm writing a cross platform Xamarin background application and want to use Shiny.
I have got a service interface and platform specific concrete implementations of the class.
I'm sure its something simple but the piece of the puzzle I am missing is how to register the interface in the Shiny DI container so that the correct platform specific implementation is used.
If I was doing this without Shiny I would have my own DI container in the App class and initialise that from each platform. With Shiny, I only seem to have the ShinyStart class where I can get to the services collection but that does not have access to the concrete classes.
I have looked into Shiny modules but cannot figure out from the documentation how they get around the issue either
How do I get access to the Shiny DI service container from within platform specific code so I can register the correct concrete class against the interface?
Regards
Brian
If anybody else is interested in this I found the answer buried in the shiny code. You have to define a MainApplication class and use RegeisterPlatformServices.
public partial class MainApplication : global::Android.App.Application
{
public MainApplication(IntPtr handle, JniHandleOwnership transfer) :
base(handle, transfer) {}
public override void OnCreate()
{
this.ShinyOnCreate(new global::ElevateNfc.ShinyStartup
{
RegisterPlatformServices = services =>
{
services.AddSingleton<IManager, Manager>();
}
});
global::Xamarin.Essentials.Platform.Init(this);
base.OnCreate();
}
}
I register my Xamarin form page with Autofac container on my App that inherits PrismApplication för Autofac
_container.RegisterTypeForNavigation<MasterLayoutPage_View, MasterLayoutPageViewModel>("MasterLayoutPage");
Then I navigate like this:
await NavigationService.NavigateAsync("MasterLayoutPage");
But it always says that MasterLayoutPage is not registered.
But when I check my Container for registered types it's there, fully added as the registration above.
Have I missed something? It worked with Unity I just change to Autofac.
I found this kind of odd and wonder if it might be a bug or if NavigationService with Autofact can't register the type as Unity can?
Seems like my problem was that I did not register the pages inside the override method RegisterTypes on App.xaml.cs I registered the types on the Initialize overridden method. It did work with Unity, not sure why it does not work the same way with autofac when it's the same container I use... Maybe prismApplication for unity has some difference then PrismApplication for Autofac, I shall take a look at the implementations of those two
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.
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.
I'm using StructureMap for IoC and it works fine for regular controllers but I can't make it work with Areas. I have the following AccountController in Administration Area:
public class AccountController : Controller
{
private readonly IFormsAuthenticationService formsService;
private readonly IMembershipService membershipService;
public AccountController(IFormsAuthenticationService formsService, IMembershipService membershipService)
{
this.formsService = formsService;
this.membershipService = membershipService;
}
...
}
And here's the error:
System.InvalidOperationException: An error occurred when trying to create a controller of type 'Foo.Areas.Administration.Controllers.AccountController'. Make sure that the controller has a parameterless public constructor. ---> System.MissingMethodException: No parameterless constructor defined for this object.
Any help would be greatly appreciated!
EDIT
StructureMap couldn't resolve MembershipProvider.
Here's the solution:
For<MembershipProvider>().Use(Membership.Providers["AspNetSqlMembershipProvider"]);
I doubt that this is a problem with areas because I am using them happily. It is more likely a pure IOC issue. You get this error when one of the injected services cannot be resolved by your container, which has the consequence that the container cannot match a signature for the constructor and tries to fall back to the empty constructor, which doesn't exist, rightly.
So, my first instinct would be to make sure that the two injected services are available. It is possible that one of them did not get created properly; a common cause is that the Membership provider cannot connect to its database, or similar.
For diagnosing, in your global.asax, after the container has been created, see if you can manually resolve those two services. I don't know SM, but something like:
var s = container.Resolve<IMembershipService>();
Satisfy yourself that both those services can be resolved.