How to inject a generic interface into MVC controller using Ninject - c#

I have the following situation:
an interface:
public interface ITest<T> where T:class
{
void Delete(T item);
}
the abstract implementation:
public abstract class Test<T>:ITest<T> where T:class
{
private readonly ApplicationDbContext _context;
protected Test(ApplicationDbContext context){
_context=context;
}
public void Delete(T item) { }
}
final class:
public class RepoTest:Test<FirstEntity>
{
public void DoSomething() { }
}
I have a MVC Controller, which looks like this:
public abstract class MyController<T>:Controller where T:class
{
private readonly ITest<T> _test;
protected MyController(ITest<T> test)
{
_test = test;
}
}
For each entity, I create a controller, inherited from MyController, and base on Entity I want ninject to inject the specific class.
For this I try to use this bindings:
kernel.Bind(typeof(ITest<>)).To(typeof(Test<>)).InRequestScope();
kernel.Bind(x=>x.FromAssemblyContaining(typeof(Test<>))
.SelectAllClasses()
.InheritedFrom(typeof(Test<>))
.BindToSelf());
Unfortunatly I alwasys got this kind of errors:
Error activating ITest{Tool}
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency ITest{Tool} into parameter test of constructor of type ToolsController
1) Request for ToolsController
Suggestions: 1) Ensure that you have defined a binding for
ITest{Tool}. 2) If the binding was defined in a module, ensure that
the module has been loaded into the kernel. 3) Ensure you have not
accidentally created more than one kernel. 4) If you are using
constructor arguments, ensure that the parameter name matches the
constructors parameter name. 5) If you are using automatic module
loading, ensure the search path and filters are correct.
How can I tell to Ninject, to inject the class base on the Entity type?

The code as it is written currently won't work.
You have two options:
Use generic:
Because your controller is expecting ITest<T> which is bound to an abstract class Test<T> which can't be instantiated.
You have to make a concrete but Generic class Test<T> and add a binding for ApplicationDbContext which will automatically work.
Use Reflection to find the right type at binding, e.g.:
Important!!! remove both of your kernel.Bind() calls.
// this will find classes which, like RepoTest, are derived from Test<>
var allDerivedTypes = typeof(Test<>).Assembly.GetExportedTypes().Where(x => x.BaseType.IsGenericType && x.BaseType.GetGenericTypeDefinition() == typeof(Test<>)).ToList();
// ideally, you'd find some way to constrain all your models.
// what you need for this foreach is all of the entities that can be present in things like RepoTest
foreach(var t in typeof(Tool).Assembly.GetExportedTypes())
{
// For each entity, get a runtime representation of Test<Entity>
var targetType = typeof(Test<>).MakeGenericType(t);
// Check if there is a class derived from Test<Entity>
var potentiallyPresentImplementation = allDerivedTypes.FirstOrDefault(x => targetType == x.BaseType); // here you might want to decide how to handle multiple instances of the same generic base
// Found one, so bind it
if(potentiallyPresentImplementation != null)
{
kernel.Bind(targetType ).To(potentiallyPresentImplementation ).InRequestScope();
}
}
Note: method 2 is currently assuming that all models and Test<> derivatives are in one assmebly, respecitvely. You'd need to add a little more reflection magic to inspect all referenced assemblies if this is not the case.
After this, the controller will get RepoTest injected. Although to be honest with you, approach 1. is better :)

Related

Dependency Injection and Generics

I'm having trouble with getting generics and DI to work together in an MVC Core project. I have a generic class (this is just a fragment). I need to initialize Input and Output because of how these are used in other parts of the code, so I'm using Activator to provide initial values and the new() constraint.
public class Message<TIn, TOut> :
where TIn : class, IMessagePart, new()
where TOut : class, IMessagePart, new() {
public Message(){}
public Message(TIn inpart, TOut outpart) {
Input = inpart;
Output = outpart;
}
public TIn Input { get; set; } = (TIn)Activator.CreateInstance(typeof(TIn));
public TOut Output { get; set; } = (TOut)Activator.CreateInstance(typeof(TOut));
}
I have other classes that are used by this, and they have some static utility classes. I'm trying to replace these static classes using DI.
public class Project : IMessagePart{
int y = 1;
var x = StaticUtilityClass.StaticMethod(y);
}
is used like this
var projectMessage = new Message<Project, Project>();
I'm converting the static utility classes to instance classes and injecting them. I'm using the built-in .Net core container. I converted the utilities to instance classes and registered them as concrete singletons in the container. For most things I can just do the normal-
public class SomeClass{
private readonly UtilityClass _utility;
public SomeClass(UtilityClass utility){
_utility = utility;
var x = _utility.Method(1);
}
Things work fine until I get to the generics. I can't do constructor injection on projectMessage, because the generic needs to new it up and it has the new() constraint, so I need a parameterless constructor. If I add just the an injecting constructor I get
'Project' must be a non-abstract type with a public parameterless
constructor in order to use it as parameter 'TIn' in the generic type
or method 'Message'.
and if I add both constructors Activator is only going to call the one without parameters, so DI isn't invoked. I tried using the overload of CreateInstance a few different ways, but no luck tricking it.
Any suggestions here? I don't know if I should stay with statics, try some sort of service locator approach, or if there is a different way to writing the generic.
The answer to why you are getting the error you're seeing is the new() constraints. That specifies that the parameter must have a public parameterless constructor. Which is exactly what your error says. Removing that constraint should fix that error. However, you still have another issue if you want to use DI.
Aside from IMessagePart none of your classes have backing interfaces. In order to use DI effectively you need to define an IMessage, IProject etc. Then your container can create specific instances at runtime, rather than using the Activators like you are now. So your Message declaration would look like:
public class Message<TIn, TOut> : IMessage,
where TIn : class, IMessagePart
where TOut : class, IMessagePart
{
public TIn input { get; set; }
public TOut output { get; set; }
public Message(TIn inpart, TOut outpart) {
this.input = inpart;
this.output = outpart;
}
}
You would setup your DI container something like:
public Startup()
{
var container = new DiContainer(); // I know this is the wrong name; I'm not familiar with the built in container naming and functionality.
container.Register<IMessage>();
container.Register<IMessagePart>();
container.Register<IProject>();
// Register other stuff here
}
Change the syntax there for your specific container. You also have the option of registering your instances something like:
container.Register<Message>(() => Message(part1, part2));
so that you specifically inject a Message that is newed up at Startup time, but that's not really ideal in most cases. Usually you want your DI container to dynamically create an instance as needed (hence the interfaces), rather than using a single concrete instantiation. There are exceptions of course; a SQL connection is one common one.

Reflection - create and register constructors dynamically from assembly

I'm working with an object which registers other classes within it by passing that class's constructor, i.e. I have classes to register, all of them within the same assembly.
configurator.Register(new MyAwesomeClass());
What I want to do is to be able to pass the type MyAwesomeClass to a generator-type class, and have it handle all of the registration through reflection. Now, the class MyAwesomeClass is derived from some generics and has some type restrictions on it which are giving my issues. Namely, it's structure is as follows:
public class MyAwesomeClass : MyBaseClass<AwesomeThing>
{
public MyAwesomeClass()
{ }
}
public abstract class MyBaseClass<T> : IDomain<T> where T : class, IEntity, new()
The AwesomeThing class is just a plain old object with some basic properties. Finaly, the actual registry function is defined in an interface follows:
public interface IConfigurator
{
void Register<T>(IDomain<T> domain)
where T : class, IEntity, new();
}
What I'm trying to do is to dynamically create these constructors from reflection based on the assembly containing 'MyAwesomeClass.' What I have been trying so far is to use reflection to create a register of lambda expressions based on an assembly we pass in. In short:
public class ConfigRegistryCreator<IConfig>
{
ConfigRegistryCreator(Type myAwesomeClassType)
{
_myAwesomeClassConstructors = new List<Func<IDomain<>>();
}
private List<Func<IDomain<>>> _myAwesomeClassConstructors;
private void RegisterTypes(Type myAwesomeClassType)
{
var q = (from t in Assembly.GetAssembly(type: myAwesomeClassType).GetTypes()
where t.IsClass && t.BaseType.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IDomain<>))
select t).ToList();
q.ForEach(t => this.Register(() => Activator.CreateInstance(t.GetType())));
}
public void Register(Func<IDomain<>> constructor)
{
_myAwesomeClassConstructors.Add(constructor);
}
public class ConfigRegistry
{
private ConfigRegistry<IConfig> _parentInstance;
{ this._parentInstance = instance; }
public void RegisterMyAwesomeClasses(IConfigurator configurator)
{
foreach(var v in this._parentInstance._myAwesomeClassConstructors)
{
configurator.Register(() => v);
}
}
}
The problem which is currently keeping me from moving on is that the configurator.Register function cannot resolve the type, because it wants to see IDomain where T is a non-abstract instance. I haven't been able to get past this. I tried changing the way I was registering classes so that I could do something like
configurator.Register((ICachingStrategy<???>)Activator.CreateInstance(t));
where t is the type I'm trying to create, but I can't find anything to use which will satisfy the compiler.
Let me know if I omitted any critical information, since I'm still new to reflection and generics and am trying to wrap my head around everything.
To be honest it was a bit difficult to follow through your question in current form, but so far it looks like you have "over-used" IDomain, try to use it just as as constraint and see how it goes.
public void Register<T>(Func<T> constructor) where T : IDomain<T>
{
_myAwesomeClassConstructors.Add(constructor);
}

Ninject interception proxying class with non empty constructor via castle dynamic proxy

I am basing most of my current implementation off the information provided here:
Ninject Intercept any method with certain attribute?
I use a custom planning strategy class which looks for all methods with given attributes (not ninject interceptor attributes) which will then get proxied if it matches the criteria.
An example of usage would be:
Kernel.Components.Add<IPlanningStrategy, CustomPlanningStrategy<LoggingAttribute, LoggerInterceptor>>();
This would then look for any methods which have a [Logging] attribute and will then use the logging interceptor.
However I am currently getting InvalidProxyConstructorArgumentsException from dynamic proxy when it is trying to proxy the methods with related attributes on. Now I remember reading that you need virtual methods, however I do not remember seeing that you HAD to have a parameterless constructor.
All bindings are done against interfaces, and the AOP interceptors happen via attributes and the custom proxy planning class mentioned in the link above.
So is there a way to get dynamic proxy (or the linfu version) to proxy the classes which have constructors with dependencies? (All dependencies are in the Kernel so its not like they cannot be resolved).
Looking at the proxy generating code:
https://github.com/ninject/ninject.extensions.interception/blob/master/src/Ninject.Extensions.Interception.DynamicProxy/DynamicProxyProxyFactory.cs
if (targetType.IsInterface)
{
reference.Instance = this.generator.CreateInterfaceProxyWithoutTarget(targetType, additionalInterfaces, InterfaceProxyOptions, wrapper);
}
else
{
object[] parameters = context.Parameters.OfType<ConstructorArgument>()
.Select(parameter => parameter.GetValue(context, null))
.ToArray();
reference.Instance = this.generator.CreateClassProxy(targetType, additionalInterfaces, ProxyOptions, parameters, wrapper);
}
one can see that ninject's dynamic proxy extension is only passing ConstructorArguments to the Castle Dynamic Proxy Generator.
So - without changes to the ninject extension or creating your own - you need to pass all dependencies as constructor arguments. You could also try out whether property / method injection works (see https://github.com/ninject/ninject/wiki/Injection-Patterns).
If you control the code you could add interfaces to the proxied classes and then use an "interface proxy with target". This allows to decouple proxy instantiation from target (proxied class) instantiation --> target can have dependencies ctor injected without any changes to ninject (-extensions).
Clarification:
Having the following class which should be proxied:
public interface IBar { }
public class Foo
{
public Foo(IBar bar)
{
}
}
And the following binding:
Bind<Foo>().ToSelf().Intercept().With<SomeInterceptor>();
Bind<IBar>().To<Bar>();
And then retrieving a Foo from the ninject container:
IResolutionRoot.Get<Foo>();
won't work.
Putting all constructor arguments on the ninject context to make it work
However, we can change the retrieving of Foo to make it work:
var bar = IResolutionRoot.Get<IBar>();
IResolutionRoot.Get<Foo>(new ConstructorArgument("bar", bar);
Now this is suboptimal because ninject is not doing dependency resolution automatically.
Adding interface to proxied class to make it work better
We can work around the issue by using a "interface proxy with target".
First, we add an interface to the proxied class:
public interface IFoo{ }
public class Foo : IFoo
{
public Foo(IBar bar)
{
}
}
And then we change the binding to:
Bind<IFoo>().To<Foo>().Intercept().With<SomeInterceptor>();
And then retrieving a Foo from the ninject container:
IResolutionRoot.Get<Foo>();
works.
Another, possibly easier (&uglier?) solution
According to #Daniel this works:
Add two constructor to the proxied type:
one protected constructor without parameters. This one is for DynamicProxy to create the proxy.
one public/internal constructor with the arguments, to be used by ninject to instantiate the proxied type.
Ninject will automatically pick the constructor with the most arguments it can resolve.
An alternate approach would be to use a convention based binding for all classes with a method with a [Logging] attribute. However, this means that adding a [Logging] attribute to a method will influence the binding of the object, which may be undesired.
So this is how it would work (verified to work):
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class LoggingAttribute : Attribute
{
}
public interface IClassNotToBeIntercepted
{
void DoSomething();
}
public class ClassNotToBeIntercepted : IClassNotToBeIntercepted
{
public void DoSomething() { }
}
public interface IClassToBeIntercepted
{
void DoNotLogThis();
void LogThis();
void LogThisAsWell();
}
public class ClassToBeIntercepted : IClassToBeIntercepted
{
public void DoNotLogThis() { }
[Logging]
public void LogThis() { }
[Logging]
public void LogThisAsWell() { }
}
public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("interceptor before {0}", BuildLogName(invocation));
invocation.Proceed();
Console.WriteLine("interceptor after {0}", BuildLogName(invocation));
}
private static string BuildLogName(IInvocation invocation)
{
return string.Format(
"{0}.{1}",
invocation.Request.Target.GetType().Name,
invocation.Request.Method.Name);
}
}
public class DemoModule : NinjectModule
{
public override void Load()
{
this.Bind(convention => convention
.FromThisAssembly()
.SelectAllClasses()
.Where(ContainsMethodWithLoggingAttribute)
.BindDefaultInterface()
.Configure(x => x
.Intercept()
.With<LoggingInterceptor>()));
this.Bind<IClassNotToBeIntercepted>()
.To<ClassNotToBeIntercepted>();
}
private static bool ContainsMethodWithLoggingAttribute(Type type)
{
return type
.GetMethods()
.Any(method => method.HasAttribute<LoggingAttribute>());
}
}
And a test:
[Fact]
public void InterceptorTest()
{
var kernel = new StandardKernel();
kernel.Load<DemoModule>();
kernel.Get<IClassNotToBeIntercepted>()
.DoSomething();
kernel.Get<IClassToBeIntercepted>()
.LogThis();
}
Results in the following console output:
interceptor before ClassToBeIntercepted.LogThis
interceptor after ClassToBeIntercepted.LogThis

With Unity how do I inject a named dependency into a constructor?

I have the IRespository registered twice (with names) in the following code:
// Setup the Client Repository
IOC.Container.RegisterType<ClientEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Client", new InjectionConstructor(typeof(ClientEntities)));
// Setup the Customer Repository
IOC.Container.RegisterType<CustomerEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Customer", new InjectionConstructor(typeof(CustomerEntities)));
IOC.Container.RegisterType<IClientModel, ClientModel>();
IOC.Container.RegisterType<ICustomerModel, CustomerModel>();
But then when I want to resolve this (to use the IRepository) I have to do a manual resolve like this:
public ClientModel(IUnityContainer container)
{
this.dataAccess = container.Resolve<IRepository>(Client);
.....
}
What I would like to do is to have it resolved in the constructor (just like IUnityContainer). I need some way to say which named type to resolve to.
Something like this: (NOTE: Not real code)
public ClientModel([NamedDependancy("Client")] IRepository dataAccess)
{
this.dataAccess = dataAccess;
.....
}
Is there a way to make my fake code work?
You can configure dependencies with or without names in the API, attributes, or via the config file. You didn't mention XML above, so I'll assume you're using the API.
To tell the container to resolve a named dependency, you'll need to use an InjectionParameter object. For your ClientModel example, do this:
container.RegisterType<IClientModel, ClientModel>(
new InjectionConstructor( // Explicitly specify a constructor
new ResolvedParameter<IRepository>("Client") // Resolve parameter of type IRepository using name "Client"
)
);
This tells the container "When resolving ClientModel, call the constructor that takes a single IRepository parameter. When resolving that parameter, resolve with the name 'Client' in addition to the type."
If you wanted to use attributes, your example almost works, you just need to change the attribute name:
public ClientModel([Dependency("Client")] IRepository dataAccess)
{
this.dataAccess = dataAccess;
.....
}
This is a very late response but the question still shows up in Google.
So anyways, 5 years later...
I have a pretty simple approach. Usually when you need to use "named dependency" it's because you're trying to implement some kind of strategy pattern. In that case, I simply create a level of indirection between Unity and the rest of my code called the StrategyResolver to not be directly depending on Unity.
public class StrategyResolver : IStrategyResolver
{
private IUnityContainer container;
public StrategyResolver(IUnityContainer unityContainer)
{
this.container = unityContainer;
}
public T Resolve<T>(string namedStrategy)
{
return this.container.Resolve<T>(namedStrategy);
}
}
Usage:
public class SomeClass: ISomeInterface
{
private IStrategyResolver strategyResolver;
public SomeClass(IStrategyResolver stratResolver)
{
this.strategyResolver = stratResolver;
}
public void Process(SomeDto dto)
{
IActionHandler actionHanlder = this.strategyResolver.Resolve<IActionHandler>(dto.SomeProperty);
actionHanlder.Handle(dto);
}
}
Registration:
container.RegisterType<IActionHandler, ActionOne>("One");
container.RegisterType<IActionHandler, ActionTwo>("Two");
container.RegisterType<IStrategyResolver, StrategyResolver>();
container.RegisterType<ISomeInterface, SomeClass>();
Now, the nice thing about this is that I will never have to touch the StrategyResolver ever again when adding new strategies in the future.
It's very simple. Very clean and I kept the dependency on Unity to a strict minimum. The only time I would have touch the StrategyResolver is if I decide to change container technology which is very unlikely to happen.
Hope this helps!
Edit: I don't really like the accepted answer because when you use the Dependency attribute in your service's constructor you actually have a hard dependency on Unity. The Dependency attribute is part of the Unity library. At that point you might as well pass an IUnityContainer dependency everywhere.
I prefer having my service classes depend on objects that I completely own instead of having a hard dependency on an external library all over the place. Also using Dependency attribute makes the constructors signatures less clean and simple.
Furthermore, this technique allows to resolve named dependencies at runtime without having to hardcode the named dependencies in the constructor, in the application configuration file or use InjectionParameter which are all methods that require to know what named dependency to use at design time.
Edit (2016-09-19):
For those that might wonder, the container will know to pass itself when you are requesting IUnityContainer as dependency, as shown in the StrategyResolver constructor signature.
Edit (2018-10-20):
Here's another way, simply using a factory:
public class SomeStrategyFactory : ISomeStrategyFactory
{
private IStrategy _stratA;
private IStrategy _stratB;
public SomeFactory(IStrategyA stratA, IStrategyB stratB)
{
_stratA = stratA;
_stratB = stratB;
}
public IStrategy GetStrategy(string namedStrategy){
if (namedStrategy == "A") return _stratA;
if (namedStrategy == "B") return _stratB;
}
}
public interface IStrategy {
void Execute();
}
public interface IStrategyA : IStrategy {}
public interface IStrategyB : IStrategy {}
public class StrategyA : IStrategyA {
public void Execute(){}
}
public class StrategyB : IStrategyB {
public void Execute() {}
}
Usage:
public class SomeClass : ISomeClass
{
public SomeClass(ISomeStrategyFactory strategyFactory){
IStrategy strat = strategyFactory.GetStrategy("HelloStrategy");
strat.Execute();
}
}
Registration:
container.RegisterType<ISomeStrategyFactory, SomeStrategyFactory>();
container.RegisterType<IStrategyA, StrategyA>();
container.RegisterType<IStrategyB, StrategyB>();
container.RegisterType<ISomeClass, SomeClass>();
This 2nd suggestion is the same thing but using the factory design pattern.
Hope this helps!
You should be able to use ParameterOverrides
var repository = IOC.Container.Resolve<IRepository>("Client");
var clientModel = IOC.Container.Resolve<ClientModel>(new ParameterOverrides<ClientModel> { {"dataAccess", repository } } );
edit:
I'm not sure why you're passing around the UnityContainer - personally, we inject our dependencies into the constructor themselves (which is "normal" from what I've seen). But regardless, you can specify a name in your RegisterType and Resolve methods.
IOC.Container.RegisterType<IRepository, GenericRepository>("Client");
IOC.Container.Resolve<IRepository>("Client");
and it will give you the type you registered for that name.
Don't do this - just create a class ClientRepository : GenericRepository { } and utilise the Type system.

In a Generic Provider how to find and edit properties of T? (C#)

So, I'm making a generic provider for my repositories implementation which will be used by my BaseController (ASP.NET MVC 2) for low-level objects. These objects have common operations, such as Activate/Deactivate/Delete/Edit, so I'll always be working with the same property on each. The problem is, since I don't know what T is, I obviously don't have access to its properties.
So, my question is, can someone show me how to get the properties I need out of the objects. I've seen some people talking about Reflection, others Expression Trees, neither of which I know how to use.
I do have a generic repository which I believe uses Expression Trees (copied it from some website), but again, I don't know what I'm doing with it... If it helps, here's what I've got so far:
public class Provider<T> where T : class {
private readonly Repository<T> Repository = null;
public Provider(
Repository<T> Repository) {
this.Repository = Repository;
}
public void Activate(
int Id) {
T Entity = this.Repository.Select(Id);
// Need to get the property here, change it and move on...
this.Repository.Submit();
}
}
I'd appreciate any help on this.
If those classes have common operations, sounds like they should inherit from the same base or implement the same interface, correct? If so, use that interface/base as the constraint for T
public class Provider<T> where T : ICommonInterface
You will then have compile-time access to the shared members provided by the interface or base class.
You could make an action
public void Activate(int Id, Action<T> doSomething)
{
T Entity = this._repository.Select(Id);
// Need to get the property here, change it and move on...
doSomething(Entity);
_repository.Submit();
}
Then using the Action delegate (in this example via a lambda) the properties will be known when activate is called:
prov.Activate(5, x => x.Address = "fgfgf");
The best solution will be to give the objects a common base type, and constrain the type parameter T to be of that type. Then you'll have access to the methods or properties of the common base type at compile time:
public class Provider<T> where T : ICommon
{
...
}
or
public class Provider<T> where T : CommonBase
{
...
}
If that's not possible, then without a common base type the best you can do is reflect upon the objects to look for and invoke the property that you are interested in:
public void Activate(int Id)
{
T entity = this.Repository.Select(Id);
// Interrogate the type of the entity and get the property called "MyPropertyName"
PropertyInfo pi = entity.GetType().GetProperty("MyPropertyName");
// Invoke the property against the entity instance - this retrieves the
// value of the property.
var value = (YourType)(pi.GetValue(entity, null));
// Do somethign with the value...
this.Repository.Submit();
}
I should add that reflection is comparatively expensive and you also lose the compile time verification. But it's handy in cases like these.
You can get a MethodInfo object for working with methods by calling:
MethodInfo mi = entity.GetType().GetMethod("MyMethodName");

Categories

Resources