Prism for Xamarin.Forms with Unity and CSLA

101 views Asked by At

I'm currently working on a Xamarin.Forms application using Prism and Unity as my IoC container.

I'm also attempting to add the business logic framework CSLA to my application.

There is a Xamarin sample provided here:

https://github.com/MarimerLLC/csla/blob/main/Samples/XamarinExample/XamarinExample/XamarinExample/App.xaml.cs

In particular, everything seems to be wired up using this piece of code:

public App()
{
      InitializeComponent();

      var services = new ServiceCollection();
      services.AddCsla();

      services.AddTransient(typeof(DataAccess.IPersonDal), typeof(DataAccess.PersonDal));
      serviceProvider = services.BuildServiceProvider();
      ApplicationContext = serviceProvider.GetRequiredService<ApplicationContext>();

      MainPage = new AppShell();
}

I'm trying to figure out how to fit that sort of code / registration into the Prism framework with Unity as the IoC container. Is this a time when I'd need to use the extensions? I saw those, but I was still coming up a little short on understanding what I should be doing.

I feel like there's a fundamental misunderstanding on my part of what I should be trying to achieve here, so any guidance on what direction I should be going in would be great.

2

There are 2 answers

0
T-Rev On BEST ANSWER

I think this may be what I'm looking for:

   protected override IContainerExtension CreateContainerExtension() {
        var containerExtension = base.CreateContainerExtension();
    
        var services = new ServiceCollection();

        services.AddCsla();
        
        var serviceProvider = ((UnityContainerExtension)containerExtension).Instance.BuildServiceProvider(services);

        ApplicationContext = serviceProvider.GetRequiredService<ApplicationContext>();

        return containerExtension;
    }

Basically, it seems that I can override the container creation in my app.cs. From there I can call whatever methods I'd like against the ServiceCollection, build the container using the extension (in this case Unity) and return that container to the application.

Testing this in code I can see that I'm now able to inject the IDataPortalFactory into my view model along with the IServiceProvider, and the IServiceProvider is of type Unity.Microsoft.DependencyInjection.ServiceProvider.

    public MainPageViewModel(
        INavigationService navigationService, 
        IServiceProvider serviceProvider, 
        IDataPortalFactory dataPortalFactory, 
        ITestClassFactory testClassFactory)
        : base(navigationService) {
        Title = "Main Page";

        this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
        this.dataPortalFactory = dataPortalFactory ?? throw new ArgumentNullException(nameof(dataPortalFactory));
        this.testClassFactory = testClassFactory ?? throw new ArgumentNullException(nameof(testClassFactory));
    }

So, if I'm getting IDataPortalFactory in my view model, I'm assuming my call to AddCsla() worked, and if the IServiceProvider is considered to be a Unity service provider, I must have successfully replaced the Service Provider implementation.

4
Haukinger On

You have to dig into AddCsla() and replicate all the registrations that are done in there.

The rest is easy:

services.AddTransient(typeof(DataAccess.IPersonDal), typeof(DataAccess.PersonDal));
ApplicationContext = serviceProvider.GetRequiredService<ApplicationContext>();

is trivial to translate to Unity

unityContainer.RegisterType<DataAccess.IPersonDal, DataAccess.PersonDal>();
ApplicationContext = unityContainer.Resolve<ApplicationContext>();

or Prism's "abstraction layer"

containerRegistry.Register<DataAccess.IPersonDal, DataAccess.PersonDal>();
ApplicationContext = containerRegistry.Resolve<ApplicationContext>();