NavigationService Xamarin with Prism and Autofact can't find my navigation - xamarin

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

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.

Xamarin, How to invoke Shared code Method from Platform specific Dependency class

In Xamarin forms app, How can we invoke Shared code Method from Platform specific Dependency class.
I need to call one method implemented in my ContentPage class from my iOS dependency class.
Thanks...
There are different solutions to this:
Use a static method to call it where ever you need to.
Use the messaging center to send a message to your Shared/PCL project and do what ever you need. (link: https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/messaging-center/)
If this is a Custom renderer you can use binded command properties and Execute those in your platforms specific code.
In my case, what I did was having a static class called Helper, that contains all the static methods that I need to call on all platforms/projects.
Hope this helps.

MediatR Autofac Handler registration in Container

I'm running into an issue in my first IMediatR, Autofac MVC project. Help is much appreciated.. Thanks in advance !!!
Handler was not found for request of type
SliceProject.Services.Query.GetUserListQuery. Container or service
locator not configured properly or handlers not registered with your
container.
Autofac Container Code:
builder
.RegisterAssemblyTypes(typeof(IRequest<>).Assembly)
.Where(t => t.IsClosedTypeOf(typeof(IRequest<>)))
.AsImplementedInterfaces();
builder
.RegisterAssemblyTypes(typeof(IRequestHandler<,>).Assembly)
.Where(t => t.IsClosedTypeOf(typeof(IRequestHandler<,>)))
.AsImplementedInterfaces();
That's because you're telling Autofac to look in the assembly that contains the IRequestHandler<TRequest, TResponse> type. That type lives in the MediatR assembly, so there's no chance your handlers live in that assembly.
You have to chance the registration so it look in the assembly(ies) where your handlers are defined. If they're all defined in one single assembly, pick one handler and use it as a marker type. I tried to guess the name of one of your handlers here:
builder
.RegisterAssemblyTypes(typeof(GetUserListQueryHandler).Assembly)
.Where(t => t.IsClosedTypeOf(typeof(IRequestHandler<,>)))
.AsImplementedInterfaces();
Please also note that the registration can be made simpler with a funciton provided by Autofac, AsClosedTypesOf. It does exactly the same thing.
builder
.RegisterAssemblyTypes(typeof(GetUserListQueryHandler).Assembly)
.AsClosedTypesOf(typeof(IRequestHandler<,>)));
Finally, and this is a bit unrelated, but why do you try to register your requests in the container? Requests are usually created by custom code and not resolved from the container. In your case, it also has no effect since you made the same mistake as for handlers, that is looking for requests in the MediatR assembly, which doesn't contain any implementations of IRequest<TResponse>.

Webapi DefaultHttpControllerSelector does not properly resolve my controller

I have an WebApi application that contains some controllers (they are registered using the extension method RegisterApiControllers). This application references another assembly that contains other controllers that I don't want to expose(I have checked that they are not registered in the container). It happens that both have an OrderController, and when I try to access the /api/Order url, I get an exception "Multiple types were found that match the controller named 'order'." and the stack trace shows that I was in DefaultHttpControllerSelector.
I have seen that AutofacControllerFactory used to exist and there was even a ConfigureWebApi that registered it, but it is not anymore present in the default branch.(you can see it here http://alexmg.com/post/2012/03/09/Autofac-ASPNET-Web-API-(Beta)-Integration.aspx)
It seems also that we can not filter the namespace of the route definition in WebApi (it is possible to MVC).
So any idea on how I can use only the Controller registered in my Autofac container and not use the DefaultHttpControllerSelector that seems to scan all referenced assemblies to discover controller?
Thanks
The problem is that registering the controller with autofac is not really related to the routing process. Only once the routing process has identified which controller to dispatch to will Autofac be called to resolve the type.
It looks like, from digging around in the source, that you would need to write a replacement IHttpControllerSelector in order to handle two controllers with the same name. (which really sucks BTW).
You might be able replace the DefaultHttpControllerTypeResolver with an instance that is passed a predicate that filters out the controllers from the assembly that you want to ignore. It's a bit of a kludgy solution but might work.
Actually, you might be able to replace the DefaultHttpControllerTypeResolver completely with one that is based on registrations in your Autofac container. It is a very simple interface, so as long as Autofac have a some kind of discovery mechanism, you should be golden.
public interface IHttpControllerTypeResolver
{
ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver);
}

No parameterless constructor for the PhoneApplicationPage

I have a Windows Phone app with Ninject IOC.
At some point I realized that my MainPage.xaml.cs (initial page of the application that gets initialized first) need to have a constructor with parameters.
I have added params to a constructor like this:
public partial class MainPage : PhoneApplicationPage
{
private readonly Settings _settings;
// Constructor
public MainPage(Settings _settings)
In my Ninject modules I have the binder for Settings type:
this.Bind<Settings>().ToSelf().InSingletonScope();
However, whenever I am to run an app, I get a MissingMethodException at startup.
I have worked around this problem by retaining a parameterless constructor in my MainPage(), and I use a service locator pattern with Ninject to get the Settings instance.
I want to know if there is a way for me to still have my app service locator free?
I'm afraid this isn't possible with the way the Silverlight navigation works. You have to have the parameterless constructor. Typically you would use the service locator to resolve your ViewModel which is where you need your dependencies injected, rather than your view.
As a side note don't fall into the trap of thinking that you should be developing your mobile apps the same way as you do desktop apps. The same rules don't automatically apply. IOC is an Enterprise Design Pattern, that aims to reduce the complexity of large apps with many developers developed over long periods. Phone apps are typically small apps with few developers developed over short periods - so its not necessarily true to that you have to rigidly follow the design pattern to the letter or even at all.

Resources