Using Simple Injector with Unit Of Work & Repository Pattern in Windows Form - c#

I'm trying to implement IoC in my windows form application. My choice fell on Simple Injector, because it's fast and lightweight. I also implement unit of work and repository pattern in my apps. Here is the structure:
DbContext:
public class MemberContext : DbContext
{
public MemberContext()
: base("Name=MemberContext")
{ }
public DbSet<Member> Members { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();\
}
}
Model:
public class Member
{
public int MemberID { get; set; }
public string Name { get; set; }
}
GenericRepository:
public abstract class GenericRepository<TEntity> : IGenericRepository<TEntity>
where TEntity : class
{
internal DbContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(DbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
}
MemberRepository:
public class MemberRepository : GenericRepository<Member>, IMemberRepository
{
public MemberRepository(DbContext context)
: base(context)
{ }
}
UnitOfWork:
public class UnitOfWork : IUnitOfWork
{
public DbContext context;
public UnitOfWork(DbContext context)
{
this.context = context;
}
public void SaveChanges()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
MemberService:
public class MemberService : IMemberService
{
private readonly IUnitOfWork unitOfWork;
private readonly IMemberRepository memberRepository;
public MemberService(IUnitOfWork unitOfWork, IMemberRepository memberRepository)
{
this.unitOfWork = unitOfWork;
this.memberRepository = memberRepository;
}
public void Save(Member member)
{
Save(new List<Member> { member });
}
public void Save(List<Member> members)
{
members.ForEach(m =>
{
if (m.MemberID == default(int))
{
memberRepository.Insert(m);
}
});
unitOfWork.SaveChanges();
}
}
In Member Form I only add a textbox to input member name and a button to save to database. This is the code in member form:
frmMember:
public partial class frmMember : Form
{
private readonly IMemberService memberService;
public frmMember(IMemberService memberService)
{
InitializeComponent();
this.memberService = memberService;
}
private void btnSave_Click(object sender, EventArgs e)
{
Member member = new Member();
member.Name = txtName.Text;
memberService.Save(member);
}
}
I implement the SimpleInjector (refer to http://simpleinjector.readthedocs.org/en/latest/windowsformsintegration.html) in Program.cs as seen in the code below:
static class Program
{
private static Container container;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Bootstrap();
Application.Run(new frmMember((MemberService)container.GetInstance(typeof(IMemberService))));
}
private static void Bootstrap()
{
container = new Container();
container.RegisterSingle<IMemberRepository, MemberRepository>();
container.Register<IMemberService, MemberService>();
container.Register<DbContext, MemberContext>();
container.Register<IUnitOfWork, UnitOfWork>();
container.Verify();
}
}
When I run the program and add a member, it doesn't save to database. If I changed container.Register to container.RegisterSingle, it will save to database. From the documentation, RegisterSingle will make my class to be a Singleton. I can't using RegisterLifeTimeScope because it will generate an error
"The registered delegate for type IMemberService threw an exception. The IUnitOfWork is registered as 'Lifetime Scope' lifestyle, but the instance is requested outside the context of a Lifetime Scope"
1) How to use SimpleInjector in Windows Form with UnitOfWork & Repository pattern?
2) Do I implement the patterns correctly?

The problem you have is the difference in lifestyles between your service, repository, unitofwork and dbcontext.
Because the MemberRepository has a Singleton lifestyle, Simple Injector will create one instance which will be reused for the duration of the application, which could be days, even weeks or months with a WinForms application. The direct consequence from registering the MemberRepository as Singleton is that all dependencies of this class will become Singletons as well, no matter what lifestyle is used in the registration. This is a common problem called Captive Dependency.
As a side note: The diagnostic services of Simple Injector are able to spot this configuration mistake and will show/throw a Potential Lifestyle Mismatch warning.
So the MemberRepository is Singleton and has one and the same DbContext throughout the application lifetime. But the UnitOfWork, which has a dependency also on DbContext will receive a different instance of the DbContext, because the registration for DbContext is Transient. This context will, in your example, never save the newly created Member because this DbContext does not have any newly created Member, the member is created in a different DbContext.
When you change the registration of DbContext to RegisterSingleton it will start working, because now every service, class or whatever depending on DbContext will get the same instance.
But this is certainly not the solution because having one DbContext for the lifetime of the application will get you into trouble, as you probably already know. This is explained in great detail in this post.
The solution you need is using a Scoped instance of the DbContext, which you already tried. You are missing some information on how to use the lifetime scope feature of Simple Injector (and most of the other containers out there). When using a Scoped lifestyle there must be an active scope as the exception message clearly states. Starting a lifetime scope is pretty simple:
using (ThreadScopedLifestyle.BeginScope(container))
{
// all instances resolved within this scope
// with a ThreadScopedLifestyleLifestyle
// will be the same instance
}
You can read in detail here.
Changing the registrations to:
var container = new Container();
container.Options.DefaultScopedLifestyle = new ThreadScopedLifestyle();
container.Register<IMemberRepository, MemberRepository>(Lifestyle.Scoped);
container.Register<IMemberService, MemberService>(Lifestyle.Scoped);
container.Register<DbContext, MemberContext>(Lifestyle.Scoped);
container.Register<IUnitOfWork, UnitOfWork>(Lifestyle.Scoped);
and changing the code from btnSaveClick() to:
private void btnSave_Click(object sender, EventArgs e)
{
Member member = new Member();
member.Name = txtName.Text;
using (ThreadScopedLifestyle.BeginScope(container))
{
var memberService = container.GetInstance<IMemberService>();
memberService.Save(member);
}
}
is basically what you need.
But we have now introduced a new problem. We are now using the Service Locator anti pattern to get a Scoped instance of the IMemberService implementation. Therefore we need some infrastructural object which will handle this for us as a Cross-Cutting Concern in the application. A Decorator is a perfect way to implement this. See also here. This will look like:
public class ThreadScopedMemberServiceDecorator : IMemberService
{
private readonly Func<IMemberService> decorateeFactory;
private readonly Container container;
public ThreadScopedMemberServiceDecorator(Func<IMemberService> decorateeFactory,
Container container)
{
this.decorateeFactory = decorateeFactory;
this.container = container;
}
public void Save(List<Member> members)
{
using (ThreadScopedLifestyle.BeginScope(container))
{
IMemberService service = this.decorateeFactory.Invoke();
service.Save(members);
}
}
}
You now register this as a (Singleton) Decorator in the Simple Injector Container like this:
container.RegisterDecorator(
typeof(IMemberService),
typeof(ThreadScopedMemberServiceDecorator),
Lifestyle.Singleton);
The container will provide a class which depends on IMemberService with this ThreadScopedMemberServiceDecorator. In this the container will inject a Func<IMemberService> which, when invoked, will return an instance from the container using the configured lifestyle.
Adding this Decorator (and its registration) and changing the lifestyles will fix the issue from your example.
I expect however that your application will in the end have an IMemberService, IUserService, ICustomerService, etc... So you need a decorator for each and every IXXXService, not very DRY if you ask me. If all services will implement Save(List<T> items) you could consider creating an open generic interface:
public interface IService<T>
{
void Save(List<T> items);
}
public class MemberService : IService<Member>
{
// same code as before
}
You register all implementations in one line using Batch-Registration:
container.Register(typeof(IService<>),
new[] { Assembly.GetExecutingAssembly() },
Lifestyle.Scoped);
And you can wrap all these instances into a single open generic implementation of the above mentioned ThreadScopedServiceDecorator.
It would IMO even be better to use the command / handler pattern (you should really read the link!) for this type of work. In very short: In this pattern every use case is translated to a message object (a command) which is handled by a single command handler, which can be decorated by e.g. a SaveChangesCommandHandlerDecorator and a ThreadScopedCommandHandlerDecorator and LoggingDecorator and so on.
Your example would then look like:
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
public class CreateMemberCommand
{
public string MemberName { get; set; }
}
With the following handlers:
public class CreateMemberCommandHandler : ICommandHandler<CreateMemberCommand>
{
//notice that the need for MemberRepository is zero IMO
private readonly IGenericRepository<Member> memberRepository;
public CreateMemberCommandHandler(IGenericRepository<Member> memberRepository)
{
this.memberRepository = memberRepository;
}
public void Handle(CreateMemberCommand command)
{
var member = new Member { Name = command.MemberName };
this.memberRepository.Insert(member);
}
}
public class SaveChangesCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratee;
private DbContext db;
public SaveChangesCommandHandlerDecorator(
ICommandHandler<TCommand> decoratee, DbContext db)
{
this.decoratee = decoratee;
this.db = db;
}
public void Handle(TCommand command)
{
this.decoratee.Handle(command);
this.db.SaveChanges();
}
}
And the form can now depend on ICommandHandler<T>:
public partial class frmMember : Form
{
private readonly ICommandHandler<CreateMemberCommand> commandHandler;
public frmMember(ICommandHandler<CreateMemberCommand> commandHandler)
{
InitializeComponent();
this.commandHandler = commandHandler;
}
private void btnSave_Click(object sender, EventArgs e)
{
this.commandHandler.Handle(
new CreateMemberCommand { MemberName = txtName.Text });
}
}
This can all be registered as follows:
container.Register(typeof(IGenericRepository<>),
typeof(GenericRepository<>));
container.Register(typeof(ICommandHandler<>),
new[] { Assembly.GetExecutingAssembly() });
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(SaveChangesCommandHandlerDecorator<>));
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(ThreadScopedCommandHandlerDecorator<>),
Lifestyle.Singleton);
This design will remove the need for UnitOfWork and a (specific) service completely.

Related

How to use a factory to instantiate an interface

I have a factory to create a Generic service:
public static class AdPersisterFactory<TEntity>
where TEntity : AdBase
{
public static AdPersister<TEntity> Create(ApplicationDbContext dbContext)
{
AdRepository<TEntity> adRepository = new AdRepository<TEntity>(dbContext);
IAdImagePersister s3AdImagePersister = new S3AdImagePersister();
AdPersister<TEntity> adPersister = new AdPersister<TEntity>(adRepository, s3AdImagePersister);
return adPersister;
}
}
I want to use ninject (version 3), how can I bind IAdPersister to an instance that the above factory creates... This is my DI Code:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
// I have tried the following which does not compile
// kernel.Bind(typeof(IAdPersister<>)).ToMethod(ctx => AdPersisterFactory<>.Create(new ApplicationDbContext()));
}
This is for an ASp.NET MVC application, so ideally I don't want to use new ApplicationDbContext but use the same ApplicationDbContext which exists in RequestScope.
I have also seen Ninject.Extensions.Factory but I am not sure how/if I can use it in this scenario.
If you are willing to refactor to a more SOLID approach and AdRepository<TEntity> has a backing interface like
public class AdRepository<TEntity> : IAdRepository<TEntity>
where TEntity : AdBase {
public AdRepository(ApplicationDbContext dbContext) {
//...
}
}
And assuming...
public class AdPersister<TEntity> : IAdPersister<TEntity>
where TEntity : AdBase {
public AdPersister(IAdRepository<TEntity> adRepository, IAdImagePersister imagePersister) {
//...
}
//...
}
Then a way to create your open generic dependency would look like
private static void RegisterServices(IKernel kernel) {
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind<IAdImagePersister>().To<S3AdImagePersister>();
//Open generic bind for repository and ad persister
kernel.Bind(typeof(IAdRepository<>)).To(typeof(AdRepository<>));
kernel.Bind(typeof(IAdPersister<>)).To(typeof(AdPersister<>));
}
Now where ever the persister is needed you simple inject the closed type as
ctor(IAdPersister<Foo> fooPersister)
And the necessary dependencies will be resolved and injected by the container.
There really is no need for that static factory.
UPDATE
Based on comment I still advise to not have the static factory.
If you want to keep implementation details internal to your library then make the factory an instance class
public class AdPersisterFactory<TEntity> : IAdPersisterFactory<TEntity>
where TEntity : AdBase {
private readonly ApplicationDbContext dbContext;
public AdPersisterFactory(ApplicationDbContext dbContext) {
this.dbContext = dbContext;
}
public IAdPersister<TEntity> Create() {
AdRepository<TEntity> adRepository = new AdRepository<TEntity>(dbContext);
IAdImagePersister s3AdImagePersister = new S3AdImagePersister();
AdPersister<TEntity> adPersister = new AdPersister<TEntity>(adRepository, s3AdImagePersister);
return adPersister;
}
}
That can be registered as an open generic in your composition root.
private static void RegisterServices(IKernel kernel) {
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind(typeof(IAdPersisterFactory<>)).To(typeof(AdPersisterFactory<>));
}
and used
ctor(IAdPersisterFactory<Foo> fooPersisterFactory) {
IAdPersister<Foo> fooPersister = fooPersisterFactory.Create();
//...
}

Autofac Resolve an object which is not in Presentation Layer

I am using Autofac to resolve objects and I dont want to use constructor injection everytime in classes. Therefore I defined a base class but property injection didn't solve my problem. Everytime when I tried to reach this property on my base class from derived class, It is null.
For an example
public abstract class Service
{
public static IUnitOfWork _unitOfWork;
}
I have a base class which name is service.
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
builder.Register(c => Service.UnitOfWork = c.Resolve<IUnitOfWork>());
And my registration like on above.
I have two question about it,
Can defining UnitOfWork property as static be dangerous?
How can I resolve IUnitOfWork easily?
You definitely should consider the costructor injection pattern again and folow the advice of Mark. However to make your approach work you can do something like this:
public static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
builder.RegisterType<ServiceImpl>().As<Service>()
.OnActivated(e => Service.UnitOfWork = e.Context.Resolve<IUnitOfWork>());
var container = builder.Build();
var service = container.Resolve<Service>();
Console.WriteLine(Service.UnitOfWork);
Console.ReadKey();
}
Here ServiceImpl is a derived type from Service. As for your first question, public static fields are global variables, it is not a good idea(at all) to store UnitOfWork in this way. Moreover the whole idea of UnitOfWork contradicts with that. At least it would be better to make UnitOfWork instance property, protected it of assigning more then once and dispose it explicitlyin ServiceImpl.Dispose.
UPD: Additional example for instance property injection approach:
public class Program
{
public static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
builder.RegisterType<ServiceImpl>().As<Service>()
.OnActivated(e => e.Instance.UnitOfWork = e.Context.Resolve<IUnitOfWork>());
var container = builder.Build();
var service = container.Resolve<Service>();
Console.WriteLine(service.IsUnitOfWorkInjected);
Console.ReadKey();
}
}
public abstract class Service : IDisposable
{
private IUnitOfWork _unitOfWork;
private static readonly object padlock = new object();
public IUnitOfWork UnitOfWork
{
protected get => _unitOfWork;
set
{
if (_unitOfWork == null)
{
lock (padlock)
{
if (_unitOfWork == null)
{
_unitOfWork = value;
}
}
}
}
}
public bool IsUnitOfWorkInjected => UnitOfWork != null;
public void Dispose()
{
_unitOfWork?.Dispose();
}
}
Hope it helps.

Autofac factory of unit of work in a singleton

Plain and simple as the title suggests, is this a possible thing using Autofac dependency injection? I have been trying and searching everywhere.. I'm losing hope here.
My class has to be singleton - that can't change. I want it to take a factory of unit of works - for database transactions.
Please help me figure this one out, I'm deseperate.
Tried Func<> and registering my unit of work in every possible way (all sorts of lifetimes, externally owned or not) but failed because the DbContext within the unit of work is disposed and not created again after the first request
Edit:
Added code that will hopefully help understanding my problem:
public class SingletonDataService : IDataService
{
private _uowFactory;
public SingletonDataService(Func<IEFUnitOfWork> uowFactory)
{
_uowFactory = uowFactory
}
public List<Folder> GetAllFolders ()
{
using (uow = uowFactory())
{
return uow.FoldersRepository.GetAll();
}
}
}
public MyDbContext : DbContext
{
public DbSet<Folder> Folders {get; set;}
public DbSet<Letter> Letters {get; set;}
public MyDbContext() : base("myContext...")
}
public EFUnitOfWork : IEFUnitOfWork, IDisposable
{
public IRepository<Folder> FoldersRepository;
public IRepository<Letter> LettersRepository;
private DbContext _context;
public EFUnitOfWork(IRepository<Folder> folders, IRepository<Letter> letters, DbContext context)
{
_folders = folders;
_letters = letters;
_context = context;
}
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
_context.Dispose();
}
disposed = true;
}
}
}
public Repository<T> : IRepository<T> where T: BaseEntity
{
private DbContext _context;
private DbSet<T> _set
public Repository(DbContext context)
{
_context = context;
_set = _context.Set<T>();
}
}
public LettersController : ApiController
{
private IDataService _dataService;
public LettersController(IDataService dataService)
{
_dataService = dataService;
}
[HttpGet]
public IHttpActionResult GetAllLetters()
{
return Ok(_dataService.GetAllLetters());
}
}
// Must be singleton
builder.Register<SingletonDataService>().As(IDataService).SingleInstance();
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
builder.Register<EFUnitOfWork>().As(IEFUnitOfWork).InstancePerLifetimeScope();
builder.Register<DbContext>().As(AppDbContext).InstancePerLifetimeScope();
In the first request everything works fine, in the second third and so on I get this exception :
system.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I clearly see it happens because the context in my repository is now null, but I don't how to to change that with the DI.
What I want to achieve is so easy without DI :
How can I achieve the following with Autofac??
public class UowFactory
{
public UowFactory()
{
}
public IEFUnitOfWork Create()
{
var context = new AppDbContext()
var uow = new EFUnitOfWork(new Repository<Folder>(context), new Repository<Letter>(context), context);
return uow;
}
}
Issue
You are registering the critial components with InstancePerLifetimeScope()
When the autofac container is built it also creates a root ILifetimeScope which lives until IContainer.Dispose() is called. Now unless you create nested ILifetimeScope somewhere in the chain to the SingletonDataService, the ILifetimeScope which is used your components is the root ILifetimeScope and InstancePerLifetimeScope() effectly becomes equivalent to SingleInstance().
Solution
One of the possible solutions is to create an ILifetimeScope per IEFUnitOfWork and its children. Autofac facilitates this by providing the Owned<T> type. We can use it in conjunction with a Func<> factory (also see documentation):
public class SingletonDataService : IDataService
{
private Func<Owned<IEFUnitOfWork>> _uowFactory;
public SingletonDataService(Func<Owned<IEFUnitOfWork>> uowFactory)
{
_uowFactory = uowFactory
}
public List<Folder> GetAllFolders ()
{
using (var uow = _uowFactory())
{
return uow.Value.FoldersRepository.GetAll();
}
}
}
This should play nicely with the following registrations:
// Must be singleton
builder.Register<SingletonDataService>().As(IDataService).SingleInstance();
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
builder.Register<EFUnitOfWork>().As(IEFUnitOfWork).InstancePerLifetimeScope();
builder.Register<DbContext>().As(AppDbContext).InstancePerLifetimeScope();
However, note, that DbContext being bound with InstancePerLifetimeScope basically makes the manual disposal in EFUnitOfWork redundant.
Sidenote on proper Disposal
Since IDisposable types should support graceful multi-disposal , one should be able to simplify EFUnitOfWork.Dispose() to
public void Dispose()
{
_context.Dispose();
}
Also note, that i left out the call GC.SuppressFinalize(this);. This call is only relevant in case the class implements a custom finalizer (~EFUnitOfWork method) - or a deriving class could do so, otherwise the object is not put on the finalizer queue anyway.
Your problem is that you have a singleton (SingletonDataService) depend on a service that has a shorter lifetime (EFUnitOfWork). When the SingletonDataService instance is created by autofac, it gets an instance of EFUnitOfWork, but this instance will always stay the same (its actual lifetime will be longer than you expect) and thus gets disposed and used again, giving errors.
You have two possible solutions:
One is to create a UowFactory class like the one you defined at the bottom (but with dependencies on IRepository<Folder>, IRepository<Letter>, DbContext), register that as anything (for example singleton, but it won't matter) and make the SingletonDataService depend on it. This will likely not be a viable solution to you though, since it will also extend the lifetime of the IRepository<Folder>, IRepository<Letter>, DbContext instances and create problems there.
The proper solution is to remove the reason why you would want the SingletonDataService to be a singleton, probably some cache. And move it to a new service (CacheService?) on which the SingletonDataService depends and make that new service a singleton.

Autofac Registration technique for this specific issue

I have this class:
public class AutofacEventContainer : IEventContainer
{
private readonly IComponentContext _context;
public AutofacEventContainer(IComponentContext context)
{
_context = context;
}
public IEnumerable<IDomainEventHandler<T>> Handlers<T>(T domainEvent)
where T : IDomainEvent
{
return _context.Resolve<IEnumerable<IDomainEventHandler<T>>>();
}
}
The IEventContainer look like this:
public interface IEventContainer
{
IEnumerable<IDomainEventHandler<T>> Handlers<T>(T domainEvent)
where T : IDomainEvent;
}
Now this IEventContainer is used in a class DomainEvents like this:
public static class DomainEvents
{
....................................
....................................
public static IEventContainer Container;
public static void Raise<T>(T domainEvent) where T : IDomainEvent
{
if (Container != null)
foreach (var handler in Container.Handlers(domainEvent))
handler.Handle(domainEvent);
// registered actions, typically used for unit tests.
if (_actions != null)
foreach (var action in _actions)
if (action is Action<T>)
((Action<T>)action)(domainEvent);
}
}
My aim is to have the DomainEvents.Container registered so that all handlers are resolved.
public class SomeModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
//Wrong way in Autofac
//Because the following line is Ninject-like
DomainEvents.Container = new AutofacContainer(componentContext);
//What is the correct way to register it to achieve the above intent?
}
}
What is the way to do this in Autofac?
You are going to have a memory leak if you resolve out of the root scope. (See this post for a good overview of lifetime scopes in Autofac.) A better way to do it would be like this:
interface IEventRaiser
{
void Raise<TEvent>(TEvent #event) where TEvent : IDomainEvent;
}
class AutofacEventRaiser : IEventRaiser
{
private readonly ILifetimeScope context;
public AutofaceEventRaiser(ILifetimeScope context)
{
this.context = context;
}
public void Raise<TEvent>(TEvent #event) where TEvent : IDomainEvent
{
using(var scope = context.BeginLifetimeScope("eventRaiser"))
{
foreach(var handler in scope.Resolve<IEnumerable<IDomainEventHandler<TEvent>>>())
{
handler.Handle(#event);
}
} // scope is disposed - no memory leak
}
}
// then, in the composition root:
IContainer theContainer = BuildTheAutofacContainer();
DomainEvents.EventRaiser = new AutofacEventRaiser(theContainer);
This is the simple answer, but there is one more caveat you should be aware of...
The question is whether you really want to use a static IEventRaiser. DI purists will generally say, "no - you should inject an instance of your IEventRaiser into every class that needs one", but others have argued that a static event raiser is OK.
Be sure you are aware of how Autofac's lifetime scopes work before you make this decsion, because it could affect component sharing. For example, say SomeClass has an instance of SomeDependency and it raises SomeEvent. Let us also assume that SomeDependency is InstancePerLifetimeScope.
If SomeClass gets the IEventRaiser injected, then the handlers will be invoked on the same lifetime scope, and will be injected with the same instance of SomeDependency.
If SomeClass uses a static IEventRaiser, then the handlers will be invoked on a different lifetime scope, and will be injected with a different instance of SomeDependency.
You can see why this matters if you imagine that SomeDependency is something like a DB transaction.

Dependency Injection in WebAPI with Castle Windsor

I want to implement Dependency Injection in WebApi application using Castle Windsor. I have following sample code -
Interface -
public interface IWatch
{
{
DateTime GetTime();
}
}
Following Watch class implements IWatch Interface -
public class Watch:IWatch
{
public DateTime GetTime()
{
return DateTime.Now;
}
}
WebApi Controller - WatchController as below -
public class WatchController : ApiController
{
private readonly IWatch _watch;
public WatchController()
{
_watch = new Watch();
}
//http://localhost:48036/api/Watch
public string Get()
{
var message = string.Format("The current time on the server is: {0}", _watch.GetTime());
return message;
}
}
Currently I am initiating IWatch object with Watch in WatchController constructor. I want to remove dependency of initializing IWatch inside constructor using Windsor Castle dependency injection principle.
Can anybody provide me the steps to implement dependency injection in this case of WebApi? Thanks in advance!
CodeCaster, Noctis and Cristiano thank you for all your help and guidance..
I just got the solution for my above query -
The first step is to use nuget to install the Windsor.Castle packages in the WebApi solution.
Consider the following code snippet -
Interface IWatch.cs
public interface IWatch
{
DateTime GetTime();
}
Class Watch.cs
public class Watch:IWatch
{
public DateTime GetTime()
{
return DateTime.Now;
}
}
The ApiController WatchController.cs is defined as follows: -
public class WatchController : ApiController
{
private readonly IWatch _watch;
public WatchController(IWatch watch)
{
_watch = watch;
}
public string Get()
{
var message = string.Format("The current time on the server is: {0}", _watch.GetTime());
return message;
}
}
In the controller we have injected the dependency through IWatch object in the WatchController constructor. I have used IDependencyResolver and IDependencyScope to achieve dependency injection in web api.
The IDependencyResolver interface is used to resolve everything outside a request scope.
WindsorDependencyResolver.cs
internal sealed class WindsorDependencyResolver : IDependencyResolver
{
private readonly IWindsorContainer _container;
public WindsorDependencyResolver(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
}
public object GetService(Type t)
{
return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
}
public IEnumerable<object> GetServices(Type t)
{
return _container.ResolveAll(t).Cast<object>().ToArray();
}
public IDependencyScope BeginScope()
{
return new WindsorDependencyScope(_container);
}
public void Dispose()
{
}
}
WindsorDependencyScope.cs
internal sealed class WindsorDependencyScope : IDependencyScope
{
private readonly IWindsorContainer _container;
private readonly IDisposable _scope;
public WindsorDependencyScope(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
_scope = container.BeginScope();
}
public object GetService(Type t)
{
return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
}
public IEnumerable<object> GetServices(Type t)
{
return _container.ResolveAll(t).Cast<object>().ToArray();
}
public void Dispose()
{
_scope.Dispose();
}
}
WatchInstaller.cs
Installers are simply types that implement the IWindsorInstaller interface. The interface has a single method called Install. The method gets an instance of the container, which it can then register components with using fluent registration API:
public class WatchInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
//Need to Register controllers explicitly in your container
//Failing to do so Will receive Exception:
//> An error occurred when trying to create //a controller of type
//> 'xxxxController'. Make sure that the controller has a parameterless
//> public constructor.
//Reason::Basically, what happened is that you didn't register your controllers explicitly in your container.
//Windsor tries to resolve unregistered concrete types for you, but because it can't resolve it (caused by an error in your configuration), it return null.
//It is forced to return null, because Web API forces it to do so due to the IDependencyResolver contract.
//Since Windsor returns null, Web API will try to create the controller itself, but since it doesn't have a default constructor it will throw the "Make sure that the controller has a parameterless public constructor" exception.
//This exception message is misleading and doesn't explain the real cause.
container.Register(Classes.FromThisAssembly()
.BasedOn<IHttpController>()
.LifestylePerWebRequest());***
container.Register(
Component.For<IWatch>().ImplementedBy<Watch>()
);
}
}
Finally, we need to replace the default dependency resolver with the Windsor implementation in Global.asax.cs (Application_Start method) and install our dependencies:
private static IWindsorContainer _container;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureWindsor(GlobalConfiguration.Configuration);
}
public static void ConfigureWindsor(HttpConfiguration configuration)
{
_container = new WindsorContainer();
_container.Install(FromAssembly.This());
_container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel, true));
var dependencyResolver = new WindsorDependencyResolver(_container);
configuration.DependencyResolver = dependencyResolver;
}
Read Mark Seemann post about windsor plumbing for webapi.
I didn't work directly with Castle Windsor, but I believe the logic should be similar:
Your WatchController ctor should look like this:
public WatchController(IWatch watch)
{
_watch = watch;
}
And this is where you inject the dependency.
You should have the equivalent to a Locator in which you register your WatchController class, and tell it which watch it should receive depending on whatever you want ... design/runtime , day of the week, random number ... whatever works or whatever you need...
The following code is from MVVM-Light, but should clarify the above paragraph:
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
// This will run in design mode, so all your VS design data will come from here
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
// This will run REAL stuff, in runtime
else
{
SimpleIoc.Default.Register<IDataService, DataService>();
}
// You register your classes, so the framework can do the injection for you
SimpleIoc.Default.Register<MainViewModel>();
...
}

Categories

Resources