Sanandrea
Sanandrea

Reputation: 2194

Retrieve Custom Binding Parameters in Provider Ninject

Hi I am using Ninject in a Xamarin MVVM project. What I am trying to do is to bind specific implementations based on a enum type:

var foo = new Ninject.Parameters.Parameter("type", VMType, true);
Kernel.Get<ICommonComponentVM>(foo);

and the provider:

public class ICommonComponentVMProvider : Provider<ICommonComponentVM>
{
    protected override ICommonComponentVM CreateInstance(IContext context)
    {
         //return the implementation based on type
    }
}

which is binded in the Kernel Module as:

public class CoreModule : NinjectModule
{
    public override void Load()
    {
        Bind<ICommonComponentVM>().ToProvider<ICommonComponentVMProvider>();
    }
}

How can I extract the custom parameter from the binding IContext? Or is this the correct way to do this? The Ninject wiki lacks this info.

EDIT

I arrived at

var param = context.Parameters.Single((arg) => arg.Name == "type");

but accessing the value of the parameter with param.GetValue needs two arguments: IContext and ITarget. I have the context but what should I put as Target?

In the meantime it works with null:

var type = (CommonVMTypes)param.GetValue(context, null);

so it looks like this:

protected override ICommonComponentVM CreateInstance(IContext context)
{
    var param = context.Parameters.Single((arg) => arg.Name == "type");
    if (param == null){
        return null;
    }
    var type = (CommonVMTypes)param.GetValue(context, null); //<-- Needs an Action ITarget

    switch (type)
    // ...
}

Upvotes: 1

Views: 514

Answers (1)

BatteryBackupUnit
BatteryBackupUnit

Reputation: 13243

You can access the parameters by the property ICollection<IParameter> IContext.Parameters. You can find it by using context.Parameters.Single(x => x.Name == "type").

You could also subclass Parameter or implement IParameter for a custom parameter type with strongly typed information, p.Ex. ComponentVMTypeParameter and then select it using context.Parameters.OfType<ComponentVMTypeParameter>().Single().

Alternative approaches:

  • use conditional bindings (When(...) syntax, can check for parameters, too) instead of the providers. Does not require extending the provider.
  • use a factory instead of a provider.
  • using named bindings:
    • Bind<IFoo>().To<Foo1>().Named("Foo1")
    • IResolutionRoot.Get<IFoo>("Foo1");

However, in principle there's no need to use an IProvider. You could instead

However, if there's a limited amount of types I'd consider using an abstract factory instead

Upvotes: 2

Related Questions