bdaniel7
bdaniel7

Reputation: 197

Ninject register by convention with names

Is there a way to register with Ninject, using conventions, all classes that implement a certain interface, associated with each class' name?

interface IClientCodeValidator
{
    string ValidateClientCode(params IXpressionNode[] customParameters);
    string ValidatorName { get; }
}

public class Client1CodeValidator: IClientCodeValidator
{
    public Client1CodeValidator()
    {
         this.ValidatorName = "Client1";
    }
}

public class Client2CodeValidator: IClientCodeValidator
{
    public Client2CodeValidator()
    {
         this.ValidatorName = "Client2";
    }
}

Bind<IClientCodeValidator>()
        .To.ItsClasses()
        .InSingletonScope()
    .Named(*c => c.ValidatorName*); <--

Then later

Container.Instance.Get<IClientCodeValidator>(clientName.ToUpper())

Upvotes: 0

Views: 289

Answers (1)

Dave Thieben
Dave Thieben

Reputation: 5427

The way you're going about this is an anti-pattern called Service Locator. The recommended approach would be to use Abstract Factory instead. In that pattern, you would have an additional interface that is responsible for resolving the correct concrete implementation. For your example:

interface IClientCodeValidatorFactory
{
    IClientCodeValidator GetFor(string client);
}

public class ClientCodeValidatorFactory : IClientCodeValidatorFactory
{
    private readonly IKernel _kernel;

    public ClientCodeValidatorFactory(IKernel kernel)
    {
        _kernel = kernel;
    }

    public IClientCodeValidator GetFor(string client)
    {
        // load from your configuration how client names are associated to Validators
        return _kernel.Get<IClientCodeValidator>(validatorName)
    }
}

this way you can inject IClientCodeValidatorFactory into your constructor and avoid using Container.Instance altogether.

then you can use Ninject.Extensions.Conventions to automatically bind validators to the interface:

kernel.Bind( x => x
    .FromThisAssembly()
    .SelectAllClasses().InheritedFrom<IClientCodeValidator>()
    .BindAllInterfaces()
    .Configure(b => b.InSingletonScope()));

Upvotes: 0

Related Questions