Convert unity to autofac - c#

I am trying to convert an example piece of code I found on caching with a repository. The only problem is it's using unity for its DI and I don't have any understanding how it works.
public interface IUnitOfWork : IDisposable
{
IRepository<Blog> BlogRepository { get; }
Task<int> SaveChangesAsync();
}
public class UnitOfWork : IUnitOfWork
{
private IDataStoreContext dataStoreContext;
private readonly IUnityContainer container;
public IRepository<Blog> BlogRepository
{
get
{
// TODO : Use unity containers to generate the UnitOfwork so that to make surethat
// datacontext is a single instance in that instance of uow
return new GenericRepository<Blog>(
this.container.Resolve<ICacheStrategy<Blog>>(),
new SqlDataStoreStrategy<Blog>(this.dataStoreContext));
}
}
public UnitOfWork(IDataStoreContext dataStoreContext, IUnityContainer container)
{
this.dataStoreContext = dataStoreContext;
this.container = container;
}
public async Task<int> SaveChangesAsync()
{
return await this.dataStoreContext.SaveChangesAsync();
}
public void Dispose()
{
this.dataStoreContext.Dispose();
}
}
Can anyone point me in the right direction on how I should write this as an autofac statement?
I have only really ever need to use basic autofac e.g.
var builder = new ContainerBuilder();
// Create the container and use the default application services as a fallback
AutofacRegistration.Populate(builder, services);
builder.Register(c => new Logger())
.As<ILogger>()
.InstancePerLifetimeScope();

Related

Decorator for creating Scope with ScopedLifestyle.Flowing in Simple Injector

I need some help to understand what it's wrong in my configuration of the container.
I based this implementation by using this example.
Basically i need to implement some use case as database command based on that interface
public interface IDatabaseCommand<TResult, TParam>
{
TResult Execute(TParam commandParam);
}
and i want to use a decorator that add the transaction safe functionality.
Every command need to use a dedicated DbContext and the transaction has to be executed on that context
To do this i have implemented
Transactional Decorator:
public class TransactionDatabaseCommandDecorator
: IDatabaseCommand<DatabaseResult, BusinessCommandParams1>
{
private readonly Container _container;
private readonly Func<IDatabaseCommand<DatabaseResult, BusinessCommandParams1>>
_decorateeFactory;
public TransactionDatabaseCommandDecorator(
Container container,
Func<IDatabaseCommand<DatabaseResult, BusinessCommandParams1>> decorateeFactory)
{
_container = container;
_decorateeFactory = decorateeFactory;
}
public DatabaseResult Execute(BusinessCommandParams1 commandParam)
{
DatabaseResult res;
using (AsyncScopedLifestyle.BeginScope(_container))
{
var _command = _decorateeFactory.Invoke();
var factory = _container
.GetInstance<IDesignTimeDbContextFactory<WpfRadDispenserDbContext>>();
using (var transaction = factory.CreateDbContext(
new[] { "" }).Database.BeginTransaction())
{
try
{
res = _command.Execute(commandParam);
transaction.Commit();
}
catch (Exception e)
{
Console.WriteLine(e);
transaction.Rollback();
throw;
}
}
}
return res;
}
}
Example of implementation:
public class WpfRadDispenserUOW : IUnitOfWork<WpfRadDispenserDbContext>
{
private readonly IDesignTimeDbContextFactory<WpfRadDispenserDbContext> _factory;
private WpfRadDispenserDbContext _context;
private IDbContextTransaction _transaction;
public bool IsTransactionPresent => _transaction != null;
public WpfRadDispenserUOW(IDesignTimeDbContextFactory<WpfRadDispenserDbContext> fact)
{
_factory = fact ?? throw new ArgumentNullException(nameof(fact));
}
public WpfRadDispenserDbContext GetDbContext() =>
_context ?? (_context = _factory.CreateDbContext(null));
public IDbContextTransaction GetTransaction() =>
_transaction ?? (_transaction = GetDbContext().Database.BeginTransaction());
public void RollBack()
{
_transaction?.Rollback();
_transaction?.Dispose();
}
public void CreateTransaction(IsolationLevel isolationLevel) => GetTransaction();
public void Commit() => _transaction?.Commit();
public void Persist() => _context.SaveChanges();
public void Dispose()
{
_transaction?.Dispose();
_context?.Dispose();
}
}
Some command:
public class BusinessCommand1 : IDatabaseCommand<DatabaseResult, BusinessCommandParams1>
{
private readonly IUnitOfWork<WpfRadDispenserDbContext> _context;
public BusinessCommand1(IUnitOfWork<WpfRadDispenserDbContext> context)
{
_context = context;
}
public DatabaseResult Execute(BusinessCommandParams1 commandParam)
{
//ToDo: use context
return new DatabaseResult();
}
}
Registration of container:
var container = new Container();
container.Options.DefaultScopedLifestyle = ScopedLifestyle.Flowing;
container.Register<IDesignTimeDbContextFactory<WpfRadDispenserDbContext>>(() =>
{
var factory = new WpfRadDispenserDbContextFactory();
factory.ConnectionString =
"Server=.\\SqlExpress;Database=Test;Trusted_Connection=True";
return factory;
});
container.Register<IUnitOfWork<WpfRadDispenserDbContext>, WpfRadDispenserUOW>(
Lifestyle.Scoped);
container
.Register<IUnitOfWorkFactory<WpfRadDispenserDbContext>, WpfRadDispenserUOWFactory>();
//Command registration
container.Register<
IDatabaseCommand<DatabaseResult, BusinessCommandParams1>,
BusinessCommand1>();
//Command Decorator registration
container.RegisterDecorator(
typeof(IDatabaseCommand<DatabaseResult, BusinessCommandParams1>),
typeof(TransactionDatabaseCommandDecorator),Lifestyle.Singleton);
The problem is that when i try to execute
var transactionCommandHandler =
_container.GetInstance<IDatabaseCommand<DatabaseResult, BusinessCommandParams1>>();
usecase.Execute(new BusinessCommandParams1());
i receive correctly an instance of TransactionDatabaseCommandDecorator but when the i try to get the instance from the factory i receive this error
SimpleInjector.ActivationException: WpfRadDispenserUOW is registered using the 'Scoped' lifestyle, but the instance is requested outside the context of an active (Scoped) scope. Please see https://simpleinjector.org/scoped for more information about how apply lifestyles and manage scopes.
in SimpleInjector.Scope.GetScopelessInstance(ScopedRegistration registration)
in SimpleInjector.Scope.GetInstance[TImplementation](ScopedRegistration registration, Scope scope)
in SimpleInjector.Advanced.Internal.LazyScopedRegistration`1.GetInstance(Scope scope)
in WpfRadDispenser.DataLayer.Decorator.TransactionDatabaseCommandDecorator.Execute(BusinessCommandParams1 commandParam) in C:\Work\Git\AlphaProject\WpfRadDispenser\WpfRadDispenser.DataLayer\Decorator\TransactionDatabaseCommandDecorator.cs: riga 29
in WpfRadDispenser.Program.Main() in C:\Work\Git\AlphaProject\WpfRadDispenser\WpfRadDispenser\Program.cs: riga 47
The problem here is that i want to use a dbcontext that it's created and controlled by his decorator.
But the constructor injection it's handled by container so how i can inject the context created by the decorator inside the command?
Basically i want to having something like that made by the decorator of the command
var context = ContextFactory.GetContext();
try
{
var transaction = context.database.GetTransaction();
var command = new Command(context);
var commandParams = new CommandParams();
var ret = command.Execute(commandParams);
if (!ret.Success)
{
transaction.Discard();
return;
}
transaction.Commit();
}
catch
{
transaction.Discard();
}
but made with DI and Simple Injector
Maybe there is some issue or several issue on my design but i'm new on DI and i want to understand better how the things works.
Just to recap i need to use a lot of command database in which every command has to have an isolated context and the functionality of transaction has to be controlled by an extra layer inside the decorator.
The problem is caused by the mixture of both flowing/closure scoping vs ambient scoping. Since you are writing a WPF application, you choose to use Simple Injector's Flowing scopes feature. This allows you to resolve instances directly from a scope (e.g. calling Scope.GetInstnace).
This, however, doesn't mix with Ambient Scoping, as is what AsyncScopedLifestyle.BeginScope does.
To fix this, you will have to change the implementation of your decorator to the following:
public class TransactionDatabaseCommandDecorator
: IDatabaseCommand<DatabaseResult, BusinessCommandParams1>
{
private readonly Container _container;
private readonly Func<IDatabaseCommand<DatabaseResult, BusinessCommandParams1>>
_decorateeFactory;
public TransactionDatabaseCommandDecorator(
Container container,
Func<IDatabaseCommand<DatabaseResult, BusinessCommandParams1>> decorateeFactory)
{
_container = container;
_decorateeFactory = decorateeFactory;
}
public DatabaseResult Execute(BusinessCommandParams1 commandParam)
{
DatabaseResult res;
using (Scope scope = new Scope(_container))
{
var command = _decorateeFactory.Invoke(scope);
var factory = scope
.GetInstance<IDesignTimeDbContextFactory<WpfRadDispenserDbContext>>();
...
}
return res;
}
}
Note the following about the decorator above:
It gets injected with a Func<Scope, T> factory. This factory will create the decoratee using the provided Scope.
The execute method now creates a new Scope using new Scope(Container) instead of relying on the ambient scoping of AsyncScopedLifestyle.
The Func<Scope, T> factory is provided with the created scope.
The IDesignTimeDbContextFactory<T> is resolved from the Scope instance, instead of using the Container.

Correct way to use Autofac with Factory Pattern?

IN a Winforms project, I have set up Autofac and Factory Pattern and it looks like it's working as expected. However, I'm still not sure whether the following is best practice.
The factory class is:
public static class Client
{
public static readonly IRequestFactory RequestFactory = new RequestFactory();
}
public class Configuration
{
public IContainer Container { get; private set; }
public Configuration()
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Request"))
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
Container = builder.Build();
}
}
public class RequestFactory : IRequestFactory, IDisposable
{
private ILifetimeScope scope;
public RequestFactory()
{
scope = Client.Configuration.Container.BeginLifetimeScope();
}
public T Get<T>()
{
return scope.Resolve<T>();
}
public void Dispose()
{
if (scope != null)
{
scope.Dispose();
}
}
}
Then, classes in separate assemblies have the IRequestFactory as a ctor parameter.
Is the above the correct way to implement factor pattern with Autofac or is there a better way?

How to reuse an InstancePerRequest instance create in composition root using Autofac

I have an Asp.NET MVC5 application in which I registre my types using Autofac in Startup class in this way:
public class Startup
{
public void Configuration(IAppBuilder app)
{
IContainer container = null;
var builder = new ContainerBuilder();
// Register Services
builder.RegisterType<SalesRepository>().As<ISalesRepository>().InstancePerRequest();
builder.RegisterType<SalesService>().As<ISalesService>().InstancePerRequest();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.AsClosedTypesOf(typeof(IHandle<>))
.AsImplementedInterfaces()
.InstancePerRequest();
builder.Register<IAppEvents>(_ => new AppEvents(container)).InstancePerRequest();
// Register MVC Controllers
builder.RegisterControllers(Assembly.GetExecutingAssembly());
container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
}
}
These are my services (this is a simplified scenario, only for demonstration).
The SalesService class receives a ISalesRepository interface as dependency . In addition I have an AppEvents class where I want to resolve IHandle types:
public interface ISalesRepository { }
public class SalesRepository : ISalesRepository
{
public SalesRepository() { }
}
public interface ISalesService { }
public class SalesService : ISalesService
{
ISalesRepository _repo;
public SalesService(ISalesRepository repo)
{
_repo = repo;
}
}
public interface IHandle<T>
{
void Handle();
}
public class SalesActionHandle : IHandle<string>
{
ISalesRepository _repo;
public SalesActionHandle(ISalesRepository repo)
{
_repo = repo;
}
public void Handle() { }
}
public interface IAppEvents
{
void Raise<T>();
}
public class AppEvents : IAppEvents
{
private readonly IContainer _container;
public AppEvents(IContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
_container = container;
}
public void Raise<T>()
{
var handlers = _container.Resolve<IEnumerable<IHandle<T>>>(); // Runtime error here
foreach (var handler in handlers)
handler.Handle();
}
}
And this is my only (simplified) controller:
public class HomeController : Controller
{
ISalesService _service;
IAppEvents _events;
public HomeController(ISalesService service, IAppEvents events)
{
_service = service;
_events= events;
}
public ActionResult Index()
{
_events.Raise<string>();
return View();
}
}
The problem I have is that I get an error at this line when it is executed:
var handlers = _container.Resolve<IEnumerable<IHandle<T>>>();
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
I resolve it by doing this:
public void Raise<T>()
{
using (var scope = _container.BeginLifetimeScope("AutofacWebRequest"))
{
var handlers = scope.Resolve<IEnumerable<IHandle<T>>>();
foreach (var handler in handlers)
handler.Handle();
}
}
But in this case, when IHandle is resolved (with SalesActionHandle instance), a new instance of SalesRepository is passed as parameter in SalesActionHandle constructor. What I want is to "reuse" the same instance that SalesService is using (it was created when ISalesService was resolved. I want the same SalesRepository instance for the request)
Is there any way to achieve this behaviour?
The sample code is avaible in Github: https://github.com/josmonver/AutofacTest
You may want to use
AutofacDependencyResolver.Current.RequestLifetimeScope
to match your current request scope, but not to create a new request scope.

Resolving dbcontext per request with Unity in WebApi

I am struggling to make this work. I've got Unity and Unity.AspNet.WebApi packages (v 3.5.1404) installed and below activation code which came with the packages
public static class UnityWebApiActivator
{
/// <summary>Integrates Unity when the application starts.</summary>
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
var resolver = new UnityHierarchicalDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
// DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
/// <summary>Disposes the Unity container when the application is shut down.</summary>
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
and my type registration looks like this:
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IAuditService, AuditService>(
new PerThreadLifetimeManager(),
new InjectionConstructor(new SecurityDbContext()));
}
So far I've tried PerThreadLifetimeManager and TransientLifetimeManager with no success. I've also got the Unity.Mvc package and tried using the PerRequestLifetimeManager as suggested by msdn but no luck. It always gives me the same instance of dbcontex.
I rather do not include any MVC dependency as this is purely WebApi but when I try to use Unity.Mvc, I ended up some http runtime errors too.
Anyone has a good suggestion/example to resolve dbcontext per request with Unity in WebApi, preferably without any mvc dependency?
The way I was injecting db context was the problem here. Unity remembers the instance created and injects the same instance for all new AuditService instance created. I simply needed to resolve the db context as below.
container.RegisterType<DbContext, SecurityDbContext>(new PerThreadLifetimeManager());
PerThreadLifetimeManager did the work and it should be fine considering each web requests will be served by a different thread.
I managed to resolve per request by declaring my custom UnityResolver's class within the WebApiConfig class. The UnityResolver class uses the HttpConfiguration class assuming you're using an OWIN context.
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var _container = new UnityContainer();
DependencyConfiguration.ConfigureContainer(_container);
config.DependencyResolver = new UnityResolver(_container);
}
The ConfigureContainer class is simply a class where I declare my IOC dependencies as shown below:
private static void RegisterReleaseEnv(IUnityContainer container)
{
//Repository Registration
container
.RegisterType(typeof(IRepository<>), typeof(GenericRepository<>), new HierarchicalLifetimeManager());
}
It is very important that you use the HierarchicalLifetimeManager lifetime manager so that you get a new instance per request.
The UnityResolver class then looks like this:
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
I then get a new DB Context using a Generic Repistory as shown below:
public class GenericRepository<TEntity> : IRepository<TEntity>, IDisposable where TEntity : class
{
internal BackendContainer context;
internal DbSet<TEntity> dbSet;
public GenericRepository(BackendContainer context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public GenericRepository()
: this(new BackendContainer())
{
}
public virtual IQueryable<TEntity> All()
{
return dbSet.AsQueryable();
}
}
Because of the Unity Resolver, the Generic Repository is instantiated per request and so is the DbContext (BackendContainer).
I hope this helps.
For more information: http://www.asp.net/web-api/overview/advanced/dependency-injection

DependencyResolver + Owin + WebApi2

One of the great advantages of Owin is that it has no dependency on System.Web. How on earth do I setup the DI if WebApi clearly requires something along those lines:
var config = new HttpConfiguration();
var container = new WindsorContainer().Install(new ControllerInstaller());
container.Install(FromAssembly.This());
config.DependencyResolver = ...
Where config.DependencyResolver requires a concrete of IDependencyResolver which comes from System.Web.Http.Dependencies?
I am especially interested in C# code which uses WebApi + Owin + Castle.Windsor (Google has not helped much yet).
I have managed to get it working using:
[assembly: OwinStartup(typeof(Bla.Startup))]
namespace Bla
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
//...
var container = new WindsorContainer().Install(new ControllerInstaller());
var httpDependencyResolver = new WindsorHttpDependencyResolver(container);
config.DependencyResolver = httpDependencyResolver;
//...
}
}
public class ControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(AllTypes.FromThisAssembly()
.Pick().If(t => t.Name.EndsWith("Controller"))
.Configure(configurer => configurer.Named(configurer.Implementation.Name))
.LifestylePerWebRequest());
//...
}
}
internal 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();
}
}
internal sealed class WindsorHttpDependencyResolver : IDependencyResolver
{
private readonly IWindsorContainer _container;
public WindsorHttpDependencyResolver(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()
{
}
}
The problem I am facing is that the use of:
config.DependencyResolver = httpDependencyResolver;
introduces a dependency on system.web. So I have issues when I try to use the owin testserver in some integartion tests. I will post another question.
Take a look right here - "Dependency Injection in ASP.NET Web API with Castle Windsor by Mark Seemann". Then at Mark Seeman's blog archive. He talks a lot about DI and WEB API and he uses Castle Windsor a lot. I bet Castle Windsor is his favorite DI container. When you look at the archive do not look just for WEB API. Sometimes he posts about WEB API under different title.
If you read his excellent book you will get very good understanding on the topic of IoC/DI. Very good book.

Categories

Resources