I have defined one interface and one class:
public interface IRepository<T>
{
}
public class RoleRepository:IRepository<Domain_RoleInfo>
{
}
Inject here:
public RoleService
{
[Inject]
public RoleService(IRepository<Domain_RoleInfo> rep)
{
_roleRep=rep;
}
}
How can I perform Dependency Injection With Ninject,say how to bind?
I have written a helper class as below, it works fine with non-generic interface.but how to refactor it support generic interface as above?
public class RegisterNinjectModule : NinjectModule
{
public override void Load()
{
BindServices();
BindRepositories();
}
private void BindServices()
{
FindAndBindInterfaces("RealMVC.Service.Interfaces", "RealMVC.Services");
}
private void BindRepositories()
{
FindAndBindInterfaces("RealMVC.Repository.Interfaces", "RealMVC.Repositories");
}
private void FindAndBindInterfaces(string interfaceAssemblyName, string implAssemblyName)
{
//Get all interfaces
List<Type> interfaces = Assembly.Load(interfaceAssemblyName).GetTypes().AsQueryable().Where(x => x.IsInterface).ToList();
IQueryable<Type> ts = Assembly.Load(implAssemblyName).GetTypes().AsQueryable().Where(x => x.IsClass);
foreach (Type intf in interfaces)
{
Type t = ts.Where(x => x.GetInterface(intf.Name) != null).FirstOrDefault();
if (t != null)
{
Bind(intf).To(t).InSingletonScope();
}
}
}
}
This should work:-
Bind(typeof(IRepository<>)).To(typeof(Repository<>));
where:-
IRepository<> is an interface of the form:-
public interface IRepository<T> where T : class
{
//...
}
Repository<> is a class of the form:-
public class Repository<T> : IRepository<T> where T : class
{
//...
}
I hope this helps :-)
This should help accomplish what you are asking for.
First let us define two classes (InterfaceTypeDefinition
and BindingDefinition
).
InterfaceTypeDefinition
holds information about a concrete type and its interfaces. The method IsOpenGeneric
is define in the TypeExtensions
class.
public class InterfaceTypeDefinition
{
public InterfaceTypeDefinition(Type type)
{
Implementation = type;
Interfaces = type.GetInterfaces();
}
/// <summary>
/// The concrete implementation.
/// </summary>
public Type Implementation { get; private set; }
/// <summary>
/// The interfaces implemented by the implementation.
/// </summary>
public IEnumerable<Type> Interfaces { get; private set; }
/// <summary>
/// Returns a value indicating whether the implementation
/// implements the specified open generic type.
/// </summary>
public bool ImplementsOpenGenericTypeOf(Type openGenericType)
{
return Interfaces.Any(i => i.IsOpenGeneric(openGenericType));
}
/// <summary>
/// Returns the service type for the concrete implementation.
/// </summary>
public Type GetService(Type openGenericType)
{
return Interfaces.First(i => i.IsOpenGeneric(openGenericType))
.GetGenericArguments()
.Select(arguments => openGenericType.MakeGenericType(arguments))
.First();
}
}
BindingDefinition
holds information about the binding between a service and a concrete implementation.
public class BindingDefinition
{
public BindingDefinition(
InterfaceTypeDefinition definition, Type openGenericType)
{
Implementation = definition.Implementation;
Service = definition.GetService(openGenericType);
}
public Type Implementation { get; private set; }
public Type Service { get; private set; }
}
Second, let us implement an extension method that retrieves the necessary information.
public static class TypeExtensions
{
public static IEnumerable<BindingDefinition> GetBindingDefinitionOf(
this IEnumerable<Type> types, Type openGenericType)
{
return types.Select(type => new InterfaceTypeDefinition(type))
.Where(d => d.ImplementsOpenGenericTypeOf(openGenericType))
.Select(d => new BindingDefinition(d, openGenericType));
}
public static bool IsOpenGeneric(this Type type, Type openGenericType)
{
return type.IsGenericType
&& type.GetGenericTypeDefinition().IsAssignableFrom(openGenericType);
}
}
These classes can now be used to initialize the bindings in the module.
public class RepositoryModule : NinjectModule
{
public override void Load()
{
var definitions = Assembly.GetExecutingAssembly().GetTypes()
.GetBindingDefinitionOf(typeof(IRepository<>));
foreach (var definition in definitions)
{
Bind(definition.Service).To(definition.Implementation);
}
}
}
If you import the Ninject conventions extension, its GenericBindingGenerator
should be able to help you. It adds support for generic interfaces.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With