Dependency Injection Android - xamarin

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.

Related

How do you use Xamarin Shiny Dependency Injection

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();
}
}

Shiny + Prism + Platform Service Example

I am attempting to update a Prism 8.1 app to use Shiny v2.
In trying to turn one of my services into a Job I keep getting a container resolution error (using Unity). I am not sure what the pattern is for registering platform implementations of services. The Job has a service that is from my platform project but at the time the services.RegisterJob() is called I guess the platform initializer has not run.
Can someone post an example of how you are supposed to register platform implementations with Shiny?
Well, I'm not sure if this is the intended design but I solved the platform services this way.
I added a constructor parameter to my ShinyStartup like this:
public Startup(IPlatformInitializer platformInitializer) : base(PrismContainerExtension.Current)
{
_platformInitializer = platformInitializer;
}
and then in my AppDelegate I used this:
Shiny.ShinyHost.Init(new Shiny.ApplePlatform(), new Startup(new iOSInitializer()));
Where iOSInitializer is my Prism IPlatformInitializer.
Then in Startup I added:
protected override void RegisterServices(IContainerRegistry containerRegistry)
{
_platformInitializer.RegisterTypes(containerRegistry);
...
}
As far as the IJob not resolving dependencies when using RegisterJob, I moved job registration to App.OnStart using IJobManager.Register and it works. Also not sure if this is the intended design.
I did all my container wire up before calling RegisterJob and it still failed to resolve so there must be something under the covers that is happening in the Prism+Shiny world.

Xamarin Android using Dependency Injection

Im currently working on a DDD layer architecture. I am not sure how to use Dependency Injection on Android project solution. Currently my Android solution holds a reference to class library solution. I have used Unity on my service layer and register 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();
}
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 goes from outer to inner ?
Old question, but for future readers:
Subclassing the application class would do what you are after in regard to registering the container at start up.
[Application]
public class App : Application
{
public static UnityContainer Container { get; set; }
public App( IntPtr javaRef, JniHandleOwnership transfer ) : base( javaRef, transfer )
{
}
public override void OnCreate( )
{
base.OnCreate( );
Container = new UnityContainer( );
Container.RegisterType<ISomeService, ServiceImplementation>( );
}
}
Application Class:
https://developer.xamarin.com/api/type/Android.App.Application/
That's all I can offer at this stage... I'm still in the process of implementing a full Xam.Android solution with Unity & new to dependency injection in general.

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.

ViewModel with dependencies on Services + tombstoning

What is the recommended way to set up / inject dependencies in a viewModel after tombstoning given that when the app deactivates you typically add the ViewModel to the State dictionary and then before your app reactivates the framework deserialises the ViewModel which requires a default constructor?
If I have the class below, I would like to have dependency injection create an instance of "MyVM" injecting the dependencies for IServiceA and IServiceB. Having a default constructor would not set up the requried dependecies.
public class MyVM(IServiceA svca,IServiceB svcB)
{
}
How should the ViewModel be setup in a tombstoning scenario here?
I don't know if you're using a specific MVVM framework but Caliburn Micro has some built in features for tombstoning.
A little snippet from the docs:
public class PivotPageModelStorage : StorageHandler<PivotPageViewModel> {
public override void Configure() {
this.ActiveItemIndex()
.InPhoneState()
.RestoreAfterViewLoad();
}
}
That example is storing the ActiveItemIndex, a property on PiveotPageViewModel, in phone state but it can also store entire object graphs in PhoneState, AppSettings, or your own custom implementation. You get all that by inheriting from StorageHandler. With CM you don't have to worry about re-injecting services, it will handle that for you as it has it's own built in container.
CM WP7 Docs
In a recent Hanselman post about building a WP7 app he talked a bit about TombstoneHelper. I haven't used this one but it looks interesting.

Resources