简体   繁体   中英

Registering generic classes for generic interfaces with NInject

I Have three generic interfaces

public interface IRepositorioBase<T> where T : class {    }
public interface IServiceBase<T> where T : class {}
public interface IAppBase<T> where T : class {}

for which I have three corresponding concrete generic class implementations

public class RepositorioBase<T> where T : class {    }
public class ServiceBase<T> where T : class {}
public class AppBase<T> where T : class {}

and the other class are create using the class generics, example

public class ExpenseCardRepository : RepositoryBase<ExpenseCard>, IExpenseCardRepository{ }

public class ExpenseCardService : ServiceBase<ExpenseCard>, IExpenseCardService
{
    private readonly IExpenseCardRepository _repository;

    public ExpenseCardService(IExpenseCardRepository repository) : base(repository)
    {
        _repository = repository;
    }
}

public class ExpenseCardApp : AppBase<ExpenseCard>, IExpenseCardApp
{
    private readonly IExpenseCardService _service;

    public ExpenseCardApp(IExpenseCardService service) : base(service)
    {
        _service = service;
    }
}

I would like a generic code only to bind all types of interfaces depending on the type of class it inherits

These is example Ninject-Generic-Interface but I would like get of subclass.

What you're trying to achieve can only be done by creating an explicit binding for each type. After all IExpenseCardRepository : IRepositoryBase<ExpenseCard> is different from ICustomerRepository : IRepositoryBase<Customer> . Now the good news is that you can automate this kind of work, by using Ninject.Extension.Convention . If you stick to a naming convention, it can be done very easy. The naming convention is: Class name ends with the interface name (without a leading I of course). From your code it looks like you do. Then the solution is as easy as:

kernel.Bind(x => x.FromThisAssembly()
    .SelectAllClasses()
    .InheritedFrom(typeof(IServiceBase<>))
    .BindDefaultInterfaces());

This will bind ExpenseCardService to IExpenseCardService and IServiceBase<ExpenseCard> .


If you don't adhere to this naming convention, then things get a little more complicated: you'll have to provide (customize) the binding creation part yourself. What you would have to do is implement an IBindingGenerator and use the .BindWith<MyBindingGenerator>() extension:

kernel.Bind(x => x.FromThisAssembly()
                  .SelectAllClasses()
                  .InheritedFrom(typeof(IRepositorioBase<>))
                  .BindWith<MyBindingGenerator>());

Your binding generator would then have to decide which types to bind to and create and return those bindings.


I have to give a word of caution, though: in most cases when i've seen this kind of design it was not necessary (there was a simpler solution available). In general you should favor composition over inheritance .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM