I am building an application which uses dependency injection following the options pattern design. I have a custom ORM class named DataManager. When I create an instance of DataManager I inject the connection string into the class as below.
public class DataManager : CommonDataManager {
private readonly ConnectionStrings _connectionStrings;
public DataManager(IOptions<ConnectionStrings> options) {
this._connectionStrings = options.Value;
}
When creating the DataManager object which parameter should I use? What should the initialisation code look like?
DataManager dm = new DataManager(?);
DI integration means that the DI engine is going to be responsible for object creation. So instead of directly initializing your class, you should rather do the following. Register also your DataManager with DI, so you can later instantiate it from serviceCollection:
In your ConfigureServices method add the following:
services.AddTransient<DataManager>();
Note, that you should decide the lifespan of your instance (I've chosen Transient here, but it's up to you - Singletone, Scoped, ...).
And then when you need to instantiate it, call as follows:
serviceProvider.GetRequiredService<DataManager>();
If, however, you want to go with your approach and want to instantiate the DataManager yourself, you should get the parameter from IoC container as follows:
DataManager dm = new DataManager(sp.GetRequiredService<IOptions<ConnectionStrings>>());
Note: that in both cases I assume that you've already registered the options with the DI in your Startup.ConfigureServices method.
Related
New to Simple Injector, trying to get some pieces working for a prototype. I am creating a WPF application that uses Simple Injector and ReactiveUI, but can't seem to get explicit property injection via attribute to trigger. The specific example I am working through is just testing injection of a logger. The plan is to roll this into a decorator, but I have run across the need for attribute injection with previous projects/DI libraries. Just want to verify I am able to use it.
Snippet of the bootstrapping:
private Container RegisterDependencies(Container container = null)
{
container ??= new Container();
// Container initialization that must precede dependency registration
// occurs here
// Enable property injection via the [Import] attribute
container.Options.PropertySelectionBehavior =
new ImportPropertySelectionBehavior();
SimpleInjectorInitializer initializer = new SimpleInjectorInitializer();
Locator.SetLocator(initializer);
Locator.CurrentMutable.InitializeSplat();
Locator.CurrentMutable.InitializeReactiveUI();
container.UseSimpleInjectorDependencyResolver(initializer);
container.RegisterConditional(
typeof(ILogger),
c => typeof(NLogLogger<>)
.MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
container.Register<MainWindow>();
container.Register<ISystem, System>(Lifestyle.Singleton);
container.Verify();
return container;
}
An instance of the System is requested from the DI container in the static RunApplication called from Main:
var system = container.GetInstance<ISystem>();
And here is the property injection in the system:
public class System : ISystem
{
[Import] public ILogger Logger { get; set; }
public System()
{
// Logger is null here. NullReferenceException is thrown
Logger.LogInfo("Creating System");
}
}
At this point in the constructor, the Logger property is null and attempt to log fails with exception. I should mention the ILogger is my own abstraction of NLog. If I instead perform constructor injection:
public System(ILogger logger)
Simple Injector picks up on this and resolves the dependency fine. I have tried changing the Import attribute to a different custom-defined Dependency attribute, no change. Have also tried just instantiating the logger as a singleton, same behavior.
Really appreciate any ideas, I'm running dry on searching forums, the SimpleInjector/ReactiveUI docs, and Steven's DI book.
Edit - here is the PropertySelectionBehavior code as well:
public class PropertySelectionBehavior<T> : IPropertySelectionBehavior
where T : Attribute
{
public bool SelectProperty(
Type implementationType, PropertyInfo propertyInfo) =>
propertyInfo.GetCustomAttributes(typeof(T)).Any();
}
public class ImportPropertySelectionBehavior :
PropertySelectionBehavior<ImportAttribute> { }
2nd Edit - I can take out all of the initialization related to ReactiveUI and still reproduce same behavior. New sample looks like:
private Container RegisterDependencies(Container container = null)
{
container ??= new Container();
container.Options.PropertySelectionBehavior =
new ImportPropertySelectionBehavior();
// Logger registration
container.RegisterConditional(
typeof(ILogger),
c => typeof(NLogLogger<>)
.MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
// UI registration
container.Register<MainWindow>();
//container.Register<MainWindowViewModel>();
container.Register<ISystem, System>(Lifestyle.Singleton);
container.Verify();
return container;
}
You are using the Logger property from inside System's constructor. Properties, however, are only initialized after the constructor finished. If you remove Simple Injector from the equation, and fallback to plain old C#, you would see the same. For instance:
var system = new System() // <-- constructor call
{
Logger = new NLogLogger<System>() // Logger_set is called after the ctor
};
If you run this code, you will see the same NullReferenceException thrown by the constructor of System.
What this means is that you shouldn't use any properties from inside your constructor. Even more broadly, from a DI perspective, you shouldn't use any service inside your constructor (or during construction for that matter) as is described by Mark Seemann here.
Update, the explicit property injection is working fine. It occurs after construction. I imagine there are design reasons for this, although somehow it was contrary to my mental model that the property injection would be performed on-demand/on first use.
Planning on experimenting a bit more to see what control is available over the timing to resolve property dependencies. If anyone who is more experienced has any advice on that or can point me to additional documentation I would welcome it. The decorator sounds like the more elegant way to make sure the logger is available as expected and allow independent lazy loading of decoratee concerns. Some discussion here:
SimpleInjector - "Lazy" Instantiate a singleton that has dependencies on first use
I have a class library for caching ( Redis ), we have a unity container inside this Redis class library
public class TCache<T>
{
static readonly IUnityContainer container = new UnityContainer();
private ITCache<T> ICacheStore;
static TCache()
{
container.RegisterType<ITCache<T>, TRedisCacheStore<T>>(new ContainerControlledLifetimeManager());
}
public TCache()
{
ICacheStore = container.Resolve<TRedisCacheStore<T>>();
}
Now my senior said me not use a separate container like this and I should be using the container which is already created inside the web app with the reason being that there should be only one single container.
My question is: is it possible to access a unity container that resides in a different project and is it necessary to do this change ?
Note: I cannot add the reference of the web app into the Redis cache class library.
You should only reference a container within your composition root (http://blog.ploeh.dk/2011/07/28/CompositionRoot/).
In other words, find where your current services are registered, and perform the generic registration there.
Your type that requires a cache store then takes your abstraction via constructor injection:
public class Cache<T>
{
private readonly ITCache<T> cacheStore;
public Cache(ITCache<T> cacheStore)
{
this.cacheStore = cacheStore
?? throw new ArgumentNullException(nameof(cacheStore));
}
}
By the way, using T as a prefix for your types (rather than as a prefix for generic type parameters) is very confusing.
The names TCache and ITCache are also very confusing.
Well, I share his view of the usage of the container. How I fixed this issue is (without going into the details of how I actually created it):
Make an option to register onto the container through an interface. Something like IRegisterContainer.Register(IUnityContainer container).
Then at the moment where you now register the mappings to the container, you extend that function to also search your assembly for all objects that implement that IRegisterContainer and make them register themselves.
And use this as a platform to fix your problem.
If you want to use the IUnityContainer in your TCache object to resolve the TRediscacheStore. Simply let the IUnityContainer register itself.
container.Register<IUnityContainer, container>().
And make it a dependency in the constructor of TCache.
I use repository method to get all data from DB.
Here is the code of it:
public class ExperienceRepository
{
private readonly ToSeeDatabaseContext _context;
public ExperienceRepository(ToSeeDatabaseContext context)
{
_context = context;
}
public List<Experience> GetAllExperiences()
{
return _context.Experience.ToList();
}
}
I need to call GetAllExperience from controller.
So at first I need to declare repo as private property
I do it like this
private ExperienceRepository _exprepo = new ExperienceRepository();
But it says, it need
Severity Code Description Project File Line Suppression State
Error CS7036 There is no argument given that corresponds to the required formal parameter 'context' of 'ExperienceRepository.ExperienceRepository(ToSeeDatabaseContext)' TooSeeWeb C:\Users\EugeneSukhomlyn\source\Workspaces\TooSee\Too See Web\Too See Web\Too See Web\Controllers\ExperienceController.cs 14 Active
How I can solve it?
Since you are using dependency injection, the preferred way would be to inject the DB context to the repository.
You probably have already code similar to this in the ConfigureServices method of your Startup.cs file (or in the place where you configure your service collection if you are not using ASP.NET Core) to set up the context for dependency injection (if you don't you should add it):
services.AddDbContext<ToSeeDatabaseContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ToSeeDatabaseContext")));
Since your experience repository already accepts ToSeeDatabaseContext, it is already ready for dependency injection. Now you have to inform the DI framework about ExperienceRepository, so that it can inject it to its consumers. So in ConfigureServices you add:
services.AddTransient<ExperienceRepository, ExperienceRepository>();
Now can use dependency injection whenever you want to need the repository. In your consumer (eg. an ASP.NET page) you can use constructor injection to get a repository:
class MyExperienceConsumer {
private ExperienceRepository _exprepo;
public MyExperienceConsumer(ExperienceRepository exprepo) {
_exprepo = exprepo;
}
}
If your consumer is an ASP.NET page controller, this is all you need to do, since the MVC framework will create the controller for you and use DI to give you the repository. If you need to instantiate the consumer yourself you need to do so with the help a service provider from the DI framework, so that it can do its magic (assuming you have a service collection). When you use ActivatorUtilities, the DI framework will inject the repository into the constructor:
IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
MyExperienceConsumer consumer =
ActivatorUtilities.CreateInstance<MyExperienceConsumer>(serviceProvider);
In any case, you can use the DI framework to do the heavy lifting for you.
Your ExperienceRepository class have one constructor that requires a ToSeeDatabaseContext as parameter.
You are trying to create a instance ExperienceRepository with no parameters. The compiler can't find a constructor which doesn't take any parameters, producing the compiler error.
Consider this class with these two constructors:
public class DocumentService
{
private IDocumentDbService documentDbService;
private IDirectoryService directoryService;
private IFileService fileService;
// Constructor
public DocumentService()
{
this.documentDbService = new DocumentDbService();
this.directoryService = new DirectoryInfo();
this.filService = new FileInfo();
}
// Injection Constructor
public DocumentService(IDocumentDbService dbs, IDirectoryService ds, IFileService fs)
{
this.documentDService = dbs;
this.directoryService = ds;
this.fileService = fs;
}
}
I use the second constructor to mock the dependencies for unit testing.
Some times there are too many dependencies, so the injection constructor would have too many parameters.
So, I want to use Unity dependency injection.
Question
How can I refactor this code to use Unity instead?
(After reading Unity documents, still not sure how to use it correctly on my codes.)
Assuming you want to simplify unit test code to avoid manually setting up each dependency in every test:
You can setup container and add all necessary mocks there and than Resolve you class for the test like:
// that initialization can be shared
var container = new UnityContainer();
// register all mocks (i.e. created with Moq)
container.RegisterInstnce<IDocumentDbService>(Mock.Of<IDocumentDbService> ());
// resolve your class under test
var documentService = container.Resolve<DocumentService>();
Assert.AreEqual(42, documentService.GetSomething());
I quess you want to inject dependencies in both situations: in (unit)tests (e.g. using RhinoMocks) and real implementation (using Unity). The refactoring implies in that case that you should remove the the first constructor (of class DocumentService). Needed configuration in your dependencies should be loaded inside the dependency itself: DocumentDbService, DirectoryInfo, FileInfo. More information (like Dependency Injection Lifecycle) and some examples are available on MSDN, see https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx
I have multiple services, each of which have a UnitOfWork injected into the constructor using the Simple Injector IoC container.
Currently I can see each UnitOfWork instance is a separate object, this is bad as i am using Entity Framework and require the same context reference across all units of work.
How can I ensure the same UnitOfWork instance is injected into all services per each resolve request? My UnitOfWor will be saved by an external command handler decorator after the command completes.
Please note, this is a common library and will be used for both MVC and Windows Forms, it would be nice to have a generic solution for both platforms if possible.
Code is below:
// snippet of code that registers types
void RegisterTypes()
{
// register general unit of work class for use by majority of service layers
container.Register<IUnitOfWork, UnitOfWork>();
// provide a factory for singleton classes to create their own units of work
// at will
container.RegisterSingle<IUnitOfWorkFactory, UnitOfWorkFactory>();
// register logger
container.RegisterSingle<ILogger, NLogForUnitOfWork>();
// register all generic command handlers
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));
// register services that will be used by command handlers
container.Register<ISynchronisationService, SynchronisationService>();
container.Register<IPluginManagerService, PluginManagerService>();
}
The desired outcome of the below line is to create a object which has a shared UnitOfWork instance throughout the constructed object graph:
var handler = Resolve<ICommandHandler<SyncExternalDataCommand>>();
Here are my services:
public class PluginManagerService : IPluginSettingsService
{
public PluginManagerService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
private readonly unitOfWork;
void IPluginSettingsService.RegisterPlugins()
{
// manipulate the unit of work
}
}
public class SynchronisationService : ISynchronisationService
{
public PluginManagerService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
private readonly unitOfWork;
void ISynchronisationService.SyncData()
{
// manipulate the unit of work
}
}
public class SyncExternalDataCommandHandler
: ICommandHandler<SyncExternalDataCommand>
{
ILogger logger;
ISynchronisationService synchronisationService;
IPluginManagerService pluginManagerService;
public SyncExternalDataCommandHandler(
ISynchronisationService synchronisationService,
IPluginManagerService pluginManagerService,
ILogger logger)
{
this.synchronisationService = synchronisationService;
this.pluginManagerService = pluginManagerService;
this.logger = logger;
}
public void Handle(SyncExternalDataCommand command)
{
// here i will call both services functions, however as of now each
// has a different UnitOfWork reference internally, we need them to
// be common.
this.synchronisationService.SyncData();
this.pluginManagerService.RegisterPlugins();
}
}
Which registration you need depends on the type of application. Since you are talking about two different frameworks (MVC and WinForms), both will have a different registration.
For an MVC application (or web applications in general), the most common thing to do is to register the unit of work on a per web request basis. For instance, the following registration will cache the unit of work during a single web request:
container.Register<IUnitOfWork>(() =>
{
var items = HttpContext.Current.Items;
var uow = (IUnitOfWork)items["UnitOfWork"];
if (uow == null)
{
items["UnitOfWork"] = uow = container.GetInstance<UnitOfWork>();
}
return uow;
});
The downside of this registration is that the unit of work is not disposed (if needed). There is an extension package for the Simple Injector that adds RegisterPerWebRequest extension methods to the container, which will automatically ensure that the instance is disposed at the end of the web request. Using this package, you will be able to do the following registration:
container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
Which is a shortcut to:
container.Register<IUnitOfWork, UnitOfWork>(new WebRequestLifestyle());
A Windows Forms application on the other hand, is typically single threaded (a single user will be using that application). I believe it is not unusual to have a single unit of work per form, which is disposed the form closes, but with the use of the command/handler pattern, I think it is better to take a more service oriented approach. What I mean by this is that it would be good to design it in such way that you can move the business layer to a WCF service, without the need to make changes to the presentation layer. You can achieve this by letting your commands only contain primitives and (other) DTOs. So don't store Entity Framework entities into your commands, because this will make serializing the command much harder, and it will lead to surprises later on.
When you do this, it would be convenient to create a new unit of work before the command handler starts executing, reuse that same unit of work during the execution of that handler, and commit it when the handler completed successfully (and always dispose it). This is a typical scenario for the Per Lifetime Scope lifestyle. There is an extension package that adds RegisterLifetimeScope extension methods to the container. Using this package, you will be able to do the following registration:
container.RegisterLifetimeScope<IUnitOfWork, UnitOfWork>();
Which is a shortcut to:
container.Register<IUnitOfWork, UnitOfWork>(new LifetimeScopeLifestyle());
The registration however, is just half of the story. The second part is to decide when to save the changes of the unit of work, and in the case of the use of the Lifetime Scope lifestyle, where to start and end such a scope. Since you should explicitly start a lifetime scope before the command executes, and end it when the command finished executing, the best way to do this, is by using a command handler decorator, that can wrap your command handlers. Therefore, for the Forms Application, you would typically register an extra command handler decorator that manages the lifetime scope. This approach does not work in this case. Take a look at the following decorator, but please note that it is incorrect:
private class LifetimeScopeCommandHandlerDecorator<T>
: ICommandHandler<T>
{
private readonly Container container;
private readonly ICommandHandler<T> decoratedHandler;
public LifetimeScopeCommandHandlerDecorator(...) { ... }
public void Handle(T command)
{
using (this.container.BeginLifetimeScope())
{
// WRONG!!!
this.decoratedHandler.Handle(command);
}
}
}
This approach does not work, because the decorated command handler is created before the lifetime scope is started.
We might be tempted into trying to solve this problem as follows, but that isn't correct either:
using (this.container.BeginLifetimeScope())
{
// EVEN MORE WRONG!!!
var handler = this.container.GetInstance<ICommandHandler<T>>();
handler.Handle(command);
}
Although requesting an ICommandHandler<T> inside the context of a lifetime scope, does indeed inject an IUnitOfWork for that scope, the container will return a handler that is (again) decorated with a LifetimeScopeCommandHandlerDecorator<T>. Calling handler.Handle(command) will therefore result in a recursive call and we'll end up with a stack overflow exception.
The problem is that the dependency graph is already built before we can start the lifetime scope. We therefore have to break the dependency graph by deferring building the rest of the graph. The best way to do this that allows you to keep your application design clean] is by changing the decorator into a proxy and injecting a factory into it that will create the type that it was supposed to wrap. Such LifetimeScopeCommandHandlerProxy<T> will look like this:
// This class will be part of the Composition Root of
// the Windows Forms application
private class LifetimeScopeCommandHandlerProxy<T> : ICommandHandler<T>
{
// Since this type is part of the composition root,
// we are allowed to inject the container into it.
private Container container;
private Func<ICommandHandler<T>> factory;
public LifetimeScopeCommandHandlerProxy(Container container,
Func<ICommandHandler<T>> factory)
{
this.factory = factory;
this.container = container;
}
public void Handle(T command)
{
using (this.container.BeginLifetimeScope())
{
var handler = this.factory();
handler.Handle(command);
}
}
}
By injecting a delegate, we can delay the time the instance is created and by doing this we delay the construction of (the rest of) the dependency graph. The trick now is to register this proxy class in such way that it will inject the wrapped instances, instead of (of course) injecting itself again. Simple Injector supports injecting Func<T> factories into decorators, so you can simply use the RegisterDecorator and in this case even the RegisterSingleDecorator extension method.
Note that the order in which decorators (and this proxy) are registered (obviously) matters. Since this proxy starts a new lifetime scope, it should wrap the decorator that commits the unit of work. In other words, a more complete registration would look like this:
container.RegisterLifetimeScope<IUnitOfWork, UnitOfWork>();
container.RegisterManyForOpenGeneric(
typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
// Register a decorator that handles saving the unit of
// work after a handler has executed successfully.
// This decorator will wrap all command handlers.
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));
// Register the proxy that starts a lifetime scope.
// This proxy will wrap the transaction decorators.
container.RegisterSingleDecorator(
typeof(ICommandHandler<>),
typeof(LifetimeScopeCommandHandlerProxy<>));
Registering the proxy and decorator the other way around would mean that the TransactionCommandHandlerDecorator<T> would depend on a different IUnitOfWork than the rest of the dependency graph does, which would mean that all changes made to the unit of work in that graph will not get committed. In other words, your application will stop working. So always review this registration carefully.
Good luck.