0

We are trying to implement a plugin system where a Customer Project can override small bits of a Core Project in order to make the app custom to a specific customers requirements.. We are working with Xamarin, so our product is in C# and we have be trying to use Autofac or dependency injection in general to accomplish this. However, I wanted to reach out here and see if anyone has done something like this (maybe even specifically with a Xamarin project) and might have some tips or pointers. I know that is pretty open ended though so I will ask a question that can be answered more specifically. My question is this:

Has anyone implemented a plugin-like functionality that allows for a Core or Base "off-the-shelf" product to be customized via some combination of Inheritance or Dependency Injection in Xamarin, using Autofac or any other IoC? If so, what design patterns did you follow and how well has it worked for you?


IF you would like more information about what we have tried to implement so far keep reading but it's not necessary to answer my question..

Our Core product is wrapped up in a Nuget package. Whenever a new customer comes in wanting custom features, we spin up a new Customer Project that just contains a reference to the Core Nuget package. Our Core contains a Dependency Injection Container or DIContainer class which maintains a BaseContainer and CustomContainer through Autofac. On startup of the App, the BaseContainer registers all the types in the Core assembly through reflection. The CustomContainer then registers all the "custom" types which are just classes which have overridden the core class it is attempting to customize. So for example if a customer wanted a custom Main Menu the the Core MainMenuVM would look like this:

namespace MyCoreProgram.ViewModels
{
    class MainMenuVM
    {
        public MainMenuVM(object someParameter)
        {
            //Some Core work here
        }

        protected virtual void MakeTheMenu()
        {
            //do the core menu making stuff here
        }
    }
}

Then the Custom would override that core to add the custom features and register it into the CustomContainer on startup:

namespace MyCustomProgram.ViewModels
{
    class MainMenuVM : MyCoreProgram.ViewModels.MainMenuVM
    {
        public MainMenuVM(object someParameter) : base(someParameter)
        {
            //Some Custom work here
        }

        protected override void MakeTheMenu()
        {
            //do the custom menu making stuff here instead
        }
    }
}

Then the next time a MainMenuVM is called we ask our DIContainer to resolve an instance of a registered MainMenuVM instead of just instantiating a new MainMenuVM. So..

var MainMenuVM = DIContainer.GetInstance<MainMenuVM>(//send some parameters to the MainMenuVM here if needed);

So the Core doesn't care whether or not it is creating a Core or a Custom version of the MainMenuVM, as long as it gets a MainMenuVM. To give you an idea of what the DIContainer does:

public static class DIContainer
{

    static DIContainer()
    {
        //this creates the container Builders in autofac
    }

    public static void Init()
    {
        //This registers the types in the Base and Customer Assemblies into their respective containers.
    }

    public static T GetInstance<T>(params Parameter[] parameters)
    {
        if (_CustomContainer != null && _CustomContainer.IsRegistered<T>())
        {
            return CustomContainer.Resolve<T>(parameters);
        }
        else if (_BaseAsm != null && _BaseContainer.IsRegistered<T>())
        {
            return BaseContainer.Resolve<T>(parameters);
        }
        if (_CustomContainer == null || _BaseContainer == null)
        {
            throw new Exception("Init not called for DIContainer.");
        }
        return default(T);
    }
}

So you'll notice in the GetInstance method we check to see if there is a custom version of that type registered first and resolve that, or if there is not, we just resolve the base/core version instead.

It should be noted that at the moment we are saying that our Custom versions of classes have to have the same parameters. Though, I would love to find a way to make that enforced programmatically. And furthermore I would love it if we could enforce sending the right parameters to the GetInstance method instead of just relying on the coder to know what to send.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.