Dependency Injection and Generics - c#

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.

Related

Create Instance of a class from interface which it implements

Hi I am trying to build a generic UoWFactory which creates a UnitOfWork(there will be one default unitofwork and multiple custom implementaitons as well). So far I was able to create factory method which creates default UoW and returns it. I have modify the following method to return specified UoW depending on the parameter passed.
Current implementation
private BaseResult<IUnitOfWork> GetUnitOfWorkByCompiledModel<IUnitOfWork>(DbCompiledModel compiledModel)
{
return new BaseResult<IUnitOfWork>
{
Payload = new DbUnitOfWork(_context, _dbRepository, _mapper, _entityMapper)
};
}
I wish to have something like this
private BaseResult<TUoW> GetUnitOfWorkByCompiledModel<IUnitOfWork>(DbCompiledModel compiledModel) where TUoW :Class
{
return new BaseResult<TUoW>
{
//Create instance of type TUoW where TUoW can be IUnitOfWork, ICustomUnitOfWork etc
//DbUnitOfWork implements IUnitOfWork and CustomUnitOfWork implements ICustomUnitOfWork
//All the TUoW will have constructors with identical parmeters
};
}
Create an instance of class is straight forward
Activator.CreateInstance (Type type, object[] args);
But if I pass Interface type as a parameter how to create instance of DbUnitOfWork or CustomUnitOfWork.
eg:-
GetUnitOfWorkByCompiledModel<IUnitOfWork>(compiledModel);
GetUnitOfWorkByCompiledModel<ICustomUnitOfWork>(compiledModel);
Parameterless constructors
What you want is possible, except for one thing: you can't use non-default constructors with generic type arguments. You can't avoid that.
Part of the issue here is that you can't enforce specific constructor method signatures from an interface, so there is no way to guarantee that all implementation of IUnitOfWork are going to have the same constructor.
The simplest solution here is to step away from using constructors and instead use object initialization:
public interface IUnitOfWork
{
Foo Foo { get; set; }
}
private BaseResult<TUnitOfWork> GetUnitOfWorkByCompiledModel<TUnitOfWork>(DbCompiledModel compiledModel) where TUnitOfWork : IUnitOfWork, new()
{
return new BaseResult<TUnitOfWork>
{
Payload = new TUnitOfWork()
{
Foo = myFoo
};
};
}
I think this suits your expectations while being a minimal change.
Resolving interfaces
But if I pass Interface type as a parameter how to create instance of DbUnitOfWork or CustomUnitOfWork. eg
GetUnitOfWorkByCompiledModel<IUnitOfWork>(compiledModel);
GetUnitOfWorkByCompiledModel<ICustomUnitOfWork>(compiledModel);
If you intend to use interface types without concrete types, then the above answer is incomplete.
Regardless of the generic type issue, if you want to resolve an interface into a concrete type, you need to register which concrete type you want to use.
This is most commonly done via a Dependency Injection framework. These framework ask you to register all necessary types, e.g. a .NET Core example:
services.AddTransient<IUnitOfWork, MyUnitOfWork>();
services.AddTransient<ICustomUnitOfWork, MyCustomUnitOfWork>();
And the framework will then use this registration to automatically fill in constructor parameters for you:
public class Example
{
public Example(ICustomUnitOfWork uow)
{
}
}
The good practice approach here requires you to thread this dependency injection through your entire framework so you never need to call any constructor explicitly (and instead have the DI framework do it for you).
It is possible to use a service locator, which is essentially a DI framework that you call at-will. A small example of usage would be:
private BaseResult<TUnitOfWork> GetUnitOfWorkByCompiledModel<TUnitOfWork>(DbCompiledModel compiledModel) where TUnitOfWork : IUnitOfWork, new()
{
var uow = myServiceLocator.Get<TUnitOfWork>();
uow.Foo = myFoo;
return new BaseResult<TUnitOfWork>
{
Payload = uow;
};
}
This creates an instance of whichever concrete type was registered to the interface you're using as the generic parameter.
However, service locators are generally considered to be an anti-pattern, and I would strongly suggest that you avoid favor a cleaner IoC approach than this.
I can't elaborate fully on dependency injection in scope of a single StackOverflow answer. I suggest you look up dependency injection as it does exactly what you're expecting (getting a concrete type by referencing an interface)
This will be work if DbUnitOfWork Class has right name of values
What you want to change
Payload = new DbUnitOfWork(_context, _dbRepository, _mapper, _entityMapper);
Change as
Payload = new DbUnitOfWork() {
context = _context,
dbRepoitory = _dbRepository,
mapper = _mapper,
entityMapper = _entityMapper
};
hope this work.

How to decorate class that relies on a runtime value for creation

I'm brand new to using Simple Injector although I have been using Ninject for a long time, so I am comfortable with DI in general. One thing that attracted me to want to use Simple Injector was the ease of use of Decorators.
I have been able to successfully use decorators with Simple Injector in all normal cases where the dependencies are resolved when the service is requested. However, I am having a hard time figuring out if there is a way to get my decorators applied in a case when the service must be constructed using a runtime value.
In Ninject, I could pass a ConstructorArgument to the kernel.Get<IService> request that could be inherited down the chain of N decorators all the way to the "real" implementing class. I cannot figure out a way to replicate that using Simple Injector.
I have put some very basic code below to illustrate. What I would want to do in the real world would be to pass an IMyClassFactory instance into other classes in my application. Those other classes could then use it to create IMyClass instances using the IRuntimeValue they would provide. The IMyClass instance they got from the IMyClassFactory would be decorated automatically by the registered decorators.
I know I could manually apply my decorator(s) in my IMyClassFactory or any Func<IMyClass> I could come up with, but I would like it to "just work".
I keep going around and around trying to abstract out the MyClass construction, but I can't figure out how to get it to resolve with the IRuntimeValue constructor argument and be decorated.
Am I overlooking an obvious solution?
using System;
using SimpleInjector;
using SimpleInjector.Extensions;
public class MyApp
{
[STAThread]
public static void Main()
{
var container = new Container();
container.Register<IMyClassFactory, MyClassFactory>();
container.RegisterDecorator(typeof (IMyClass), typeof (MyClassDecorator));
container.Register<Func<IRuntimeValue, IMyClass>>(
() => r => container.GetInstance<IMyClassFactory>().Create(r));
container.Register<IMyClass>(() => ?????)); // Don't know what to do
container.GetInstance<IMyClass>(); // Expect to get decorated class
}
}
public interface IRuntimeValue
{
}
public interface IMyClass
{
IRuntimeValue RuntimeValue { get; }
}
public interface IMyClassFactory
{
IMyClass Create(IRuntimeValue runtimeValue);
}
public class MyClassFactory : IMyClassFactory
{
public IMyClass Create(IRuntimeValue runtimeValue)
{
return new MyClass(runtimeValue);
}
}
public class MyClass : IMyClass
{
private readonly IRuntimeValue _runtimeValue;
public MyClass(IRuntimeValue runtimeValue)
{
_runtimeValue = runtimeValue;
}
public IRuntimeValue RuntimeValue
{
get
{
return _runtimeValue;
}
}
}
public class MyClassDecorator : IMyClass
{
private readonly IMyClass _inner;
public MyClassDecorator(IMyClass inner)
{
_inner = inner;
}
public IRuntimeValue RuntimeValue
{
get
{
return _inner.RuntimeValue;
}
}
}
Edit 1:
Ok, thanks to Steven for the great answer. It has given me a couple of ideas.
Maybe to make it a little more concrete though (although not my situation, more "classic"). Say I have an ICustomer that I create at runtime by reading a DB or deserializing from disk or something. So I guess that would be considered a "newable" to quote one of the articles Steven linked. I would like to create an instance of ICustomerViewModel so I can display and manipulate my ICustomer. My concrete CustomerViewModel class takes in an ICustomer in its constructor along with another dependency that can be resolved by the container.
So I have an ICustomerViewModelFactory that has a .Create(ICustomer customer) method defined which returns ICustomerViewModel. I could always get this working before I asked this question because in my implementation of ICustomerViewModelFactory I could do this (factory implemented in composition root):
return new CustomerViewModel(customer, container.GetInstance<IDependency>());
My issue was that I wanted my ICustomerViewModel to be decorated by the container and newing it up bypassed that. Now I know how to get around this limitation.
So I guess my follow-up question is: Is my design wrong in the first place? I really feel like the ICustomer should be passed into the constructor of CustomerViewModel because that demonstrates intent that it is required, gets validated, etc. I don't want to add it after the fact.
Simple Injector explicitly lacks support for passing on runtime values through the GetInstance method. Reason for this is that runtime values should not be used when the object graph is constructed. In other words, the constructors of your injectables should not depend on runtime values. There are several problems with doing that. First of all, your injectables might need to live much longer than those runtime values do. But perhaps more importantly, you want to be able to verify and diagnose your container's configuration and that becomes much more troublesome when you start using runtime values in the object graphs.
So in general there are two solutions for this. Either you pass on the runtime value through the method call graph or you create a 'contextual' service that can supply this runtime value when requested.
Passing on the runtime value through the call graph is especially a valid solution when you practice architectures like this and this where you pass on messages through your system or when the runtime value can be an obvious part of the service's contract. In that case it is easy to pass on the runtime value with the message or the method and this runtime value will also pass through any decorator on the way through.
In your case this would mean that the factory creates the IMyService without passing in the IRuntimeValue and your code passes this value on to the IMyService using the method(s) it specifies:
var service = _myServiceFactory.Create();
service.DoYourThing(runtimeValue);
Passing through the runtime value through the call graph however is not always a good solution. Especially when this runtime value should not be part of the contract of the message that is sent. This especially holds for contextual information use as information about the current logged in user, the current system time, etc. You don't want to pass this information through; you just want it to be available. We don't want this, because this would give an extra burden to the consumers of passing the right value every time, while they probably shouldn't even be able to change this information (take the user in who's context the request is executed for instance).
In that case you should define service that can be injected and allows retrieving this context. For instance:
public interface IUserContext {
User CurrentUser { get; }
}
public interface ITimeProvider {
DateTime Now { get; }
}
In these cases the current user and the current time aren't injected directly into a constructor, but instead these services are. The component that needs to access the current user can simply call _userContext.CurrentUser and this will be done after the object is constructed (read: not inside the constructor). Thus: in a lazy fashion.
This does mean however that the IRuntimeValue must be set somewhere before MyClass gets invoked. This probably means you need to set it inside the factory. Here's an example:
var container = new Container();
var context = new RuntimeValueContext();
container.RegisterSingle<RuntimeValueContext>(context);
container.Register<IMyClassFactory, MyClassFactory>();
container.RegisterDecorator(typeof(IMyClass), typeof(MyClassDecorator));
container.Register<IMyClass, MyClass>();
public class RuntimeValueContext {
private ThreadLocal<IRuntimeValue> _runtime;
public IRuntimeValue RuntimeValue {
get { return _runtime.Value; }
set { _runtime.Value = value; }
}
}
public class MyClassFactory : IMyClassFactory {
private readonly Container _container;
private readonly RuntimeValueContext context;
public MyClassFactory(Container container, RuntimeValueContext context) {
_container = container;
_context = context;
}
public IMyClass Create(IRuntimeValue runtimeValue) {
var instance = _container.GetInstance<IMyClass>();
_context.RuntimeValue = runtimeValue;
return instance;
}
}
public class MyClass : IMyClass {
private readonly RuntimeValueContext _context;
public MyClass(RuntimeValueContext context) {
_context = context;
}
public IRuntimeValue RuntimeValue { get { return _context.Value; } }
}
You can also let the MyClass accept the IRuntimeValue and make the following registration:
container.Register<IRuntimeValue>(() => context.Value);
But the disallows verifying the object graph, since Simple Injector will ensure that registrations never return null, but context.Value will be null by default. So another option is to do the following:
container.Register<IMyClass>(() => new MyClass(context.Value));
This allows the IMyClass registration to be verified, but will during verification still create a new MyClass instance that is injected with a null value. If you have a guard clause in the MyClass constructor, this will fail. This registration however disallows MyClass to be auto-wired by the container. Auto-wiring that class can come in handy when you've got more dependencies to inject into MyClass for instance.

Unity constructor injection with implied names

I am trying to inject two classes into my constructor, the problem they are both of the same interface. My registering is:
container.RegisterType<ITrackerSection, ScopeSection>();
container.RegisterType<ITrackerSection, SampleSection>();
As you can see they are both of type ITrackerSection but have different implementations. My constructor looks as follows:
public TrackerEngine(ITrackerSection scopeSection, ITrackerSection sampleSection)
Both these parameters are injected as a sampleSection as it was last to be registered for the interface type. I have no problem with naming the registered types for example
container.RegisterType<ITrackerSection, ScopeSection>("scopeSection");
container.RegisterType<ITrackerSection, SampleSection>("sampleSection");
But this now means I have to specify the classes parameters and that seems messy and adding dependency when unity is more than capable of resolving them. Furthermore the registering of the TrackerEngine would also need to specify the parameters. I know I could use an in line attribute in the constructor of TrackerEngine but I would prefer Unity to infer the objects by the names.
Can Unity (I can not seem to get this working) correctly inject the correct implementation of the interface purely from the name given to the parameter in the constructor? So ITrackerSection scopeSection is the same name given in the registering of ScopeSection so use that type.
I agree with the comments regarding sharing the interface. The whole point of IOC is that your engine should not need to know which implementation to use. It should only be given the interface.
A way to solve this is to allow Unity to inject an array of interfaces:
public TrackerEngine(ITrackerSection[] trackerSections) { }
This way you can inject both. But then, if you really need to know which interface is which, you could implement a enum or something in your interface. Something like this:
public interface ITrackerSection {
SectionType Section { get; }
}
public enum SectionType{
0 = Scope,
1 = Sample
}
And in your implementation:
public class ScopeTrackerSection : ITrackerSection {
// Do your stuff...
public SectionType Section {
get { return SectionType.Scope; }
}
}
public class SampleTrackerSection : ITrackerSection {
// Do your stuff...
public SectionType Section {
get { return SectionType.Sample; }
}
}
And in your Engine, you can fetch the interface needed to the desired action.
public TrackerEngine(ITrackerSection[] trackerSections) {
var scopeTrackerSection = trackerSections.FirstOfDefault(x => x.Section == SectionType.Sample);
// Do something with scopeTrackerSection
}

Problems with abstract types and interafaces as generic type params with the new() constraint

I need to have the generic type parameter as an interface, however I would like to instantiate the type in the generic class (SomeGenericType) as follows:
class Program
{
static void Main(string[] args)
{
var val = new SomeGenericType<ISomeInterface>();
Console.ReadKey();
}
}
internal class SomeGenericType<T> where T : new()
{
public SomeGenericType()
{
var test = new T();
}
}
public class SomeClass : ISomeInterface
{
public string TestVal { get; set; }
}
public interface ISomeInterface
{
string TestVal { get; set; }
}
This throws the following compile time error:
"ISomeInterface must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method SomeGenericType"
I understand why it happens, however I was wondering if there is any way around this problem?
Thanks.
No, the new() constraint requires that an instance of the type can be created with the syntax
new T()
This clearly isn't true of either an abstract class or an interface, only a concrete class with a public parameterless constructor.
You could defer the problem until runtime by removing the constraint, and using:
Activator.CreateInstance<T>()
instead to create the object. Then as long as the actual type used at runtime satisfies these constraints, your code will work as you want it to. However, if you do attempt to use an interface or an abstract class, then you will encounter a runtime error.
In your specific case, this line would throw an exception
var val = Activator.CreateInstance<SomeGenericType<ISomeInterface>>();
You're past the compile-time error, but to no effect.
An alternative idea, which may be irrelevant, but it looks like you are looking for a way to ask for an ISomeInterface, and have an instance of its "default" implementation SomeClass provided. This is the sort of thing that an Inversion of Control (IOC) container can handle for you. If you want to investigate further, you could look at Spring.NET, Microsoft Unity, AutoFac, LinFu or one of many other frameworks.
The problem is, there is no way for the compiler to know which class to instantiate for the given interface. As David M points out:
This is the sort of thing that an Inversion of Control (IOC) container can handle for you
I think using a framework might be over kill for this simple requirement. What you can do is create a Factory class of your own like this:
public class Factory
{
Dictionary<Type, Type> typeMapping = new Dictionary<Type, Type>();
public void Register<IType, CType>()
{
typeMapping.Add(typeof(IType),typeof(CType));
}
public IType Create<IType>()
{
Activator.CreateInstance(typeMapping[typeof(IType)]);
}
}
throw in a few sanity checks and this class should be ready to use.
The issue here is the new constraint is tied to having a concrete type implementation. This can't ever work with simply and interface or abstract class since they cannot be directly instantiated. You must provide a concrete class here
var val = new SomeGenericType<SomeClass>()

C# - Type Parameters in Constructor - No Generics

I have a class that I am trying to do unit tests on. The class is a WCF Service Class. (Making it a generics class is not my goal.)
I have a data access layer (DAL) type (called UserDAL) that is instantiated in many methods. To get these methods under test, I need to get this local variables mocked. (Each instance of UserDAL has method specific value in it, so changing it a class level variable would result in messy code, so I would rather not do that.)
What I am thinking would be nice is to overload the constructor and pass in a type to use in the local methods. The empty param constructor would still create a normal UserDAL, but the overloaded one would have a mock type that implements IUserDAL.
I am not sure of the syntax to say I want to pass in a type. Note that I am not trying to pass in a variable, but a type.
Example:
public class MyWCFClass: IMyWCFClass
{
private TypeParam _myUserDALType;
public MyWCFClass()
{
_myUserDALType = UserDAL;
}
public MyWCFClass(TypeParam myUserDALType)
{
_myUserDALType = myUserDALType;
}
//methods to use it
public MyMethod()
{
IUserDAL userDAL = new _myUserDALType();
//Call method in IUserDAL
userDAL.CreateUser();
}
// Several similar methods that all need a different UserDAL go here
.....
}
So, I don't know what kind of type TypeParam is (I made that up) or if this kind of think is even possible.
If you have a non generics solution that would be great.
What you are really looking for is Dependency Injection, but you can do this by passing in a Type argument and then using Activator.CreateInstance(Type) to create the object when you need it.
As far as doing real DI (which will make doing this testing a lot easier), I know that Spring.Net works reasonable well.
You mean Type, using Activator.CreateInstance to create instances:
public class MyWCFClass: IMyWCFClass
{
private Type _myUserDALType;
public MyWCFClass()
{
_myUserDALType = typeof(UserDAL);
}
public MyWCFClass(Type myUserDALType)
{
_myUserDALType = myUserDALType;
}
//methods to use it
public void MyMethod()
{
IUserDAL userDAL = (IUserDAL) Activator.CreateInstance(_myUserDALType );
//Call method in IUserDAL
userDAL.CreateUser();
}
}
Use a Type, and use Activator.CreateInstance to instantiate it:
private Type _myUserDALType;
IUserDAL userDAL = Activator.CreateInstance(_myUserDALType) as IUserDAL;
Your real problem is not in the generics or lack thereof. Your real problem is that MyWFCClass is calling both new and the method. As per Misko Hevery, you get the best testability by separating classes that call new from classes that implement logic. Instead of having MyWFCClass somehow know the type that you want to implement and using reflection, just pass the IUserDal object to the constructor, allowing the test harness to pass in a mock object when needed.
If, for some reason, you can't do this and you can't use generics, then you have to do it yourself. Pass a Type object to the MyWFCClass constructor, then use reflection to find and invoke the constructor you want.
If you want to pass in a type, you can use the Type object:
public class A
{
public A(Type classType)
{
object myObject = Activator.CreateInstance(...classType...);
}
}
public class B
{
...
}
public class C
{
public static void main(string[] args)
{
A a = new A(typeof(B));
}
}
Far simpler, and more consistent with other applications that have this problem, would be to extract an interface on UserDal, then you would have something more like:
public MyWCFClass() : this(new UserDAL())
{
}
public MyWCFClass(IUserDal userDAL)
{
_myUserDAL = myUserDAL;
}
This is also easier to use with dependency-injection frameworks than your proposed method, though that's certainly a secondary concern
(Edited to clarify an alternative solution based on other comments)
If your DAL is essentially worthless after use because it is mutated, take a constructor with IUserDalFactory instead, with one method Create().
If IUserDAL defines the interface that your WCF service needs to get its job done, why not just take an instance of it as a constructor parameter? And since WCF requires a default constructor, why not have that default constructor call your parameterized constructor with a default implementation?
public class MyWCFClass : IMyWCFClass
{
private readonly IUserDAL _userDAL;
public MyWCFClass()
: this(new DefaultUserDAL())
{
}
public MyWCFClass(IUserDAL userDAL)
{
_userDAL = userDAL;
}
}
If you're using a dependency injection container, you could expose it as a singleton and satisfy the parameterized constructor by using that singleton:
public MyWCFClass()
this(Container.Instance.Resolve<IUserDAL>())
{
}
With this approach, your WCF class has everything it needs to get its job done, but it is still unit-testable. Moreover, it is not responsible for creating its dependencies, which is a good thing.
In C# there is a type called "Type". With it you can create a parameter and pass in any valid type.
private void MyMethod(Type myType)
{
//Do something
}

Categories

Resources