ImportingConstructor decorator in different projects - c#

I'm using for the first times these decorators (Export(typeOf) and ImportConstructor).
In a mvvm architecture I have a AppViewModel with the following constructor:
[ImportingConstructor]
public AppViewModel(IEventAggregator events,
PatientsManagerViewModel pmvm, TestManagerViewModel tmvm,
MainViewModel mvm)
{
patientsManagerVM = pmvm;
testManagerVM = tmvm;
mainVM = mvm;
}
and with the following Boostrapper:
public class AppBootstrapper : Bootstrapper<IShell>
{
private CompositionContainer container;
public AppBootstrapper()
{
Start();
}
protected override void Configure()
{
container = new CompositionContainer(
new AggregateCatalog(
AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()
)
);
var batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(container);
container.Compose(batch);
}
protected override object GetInstance(Type serviceType, string key)
{
string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
var exports = container.GetExportedValues<object>(contract);
if (exports.Any())
return exports.First();
throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
}
protected override IEnumerable<object> GetAllInstances(Type serviceType)
{
return container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
}
protected override void BuildUp(object instance)
{
container.SatisfyImportsOnce(instance);
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<IShell>();
}
}
The application starts without problem.
The problem comes out when i try to access another project, which is responsible for the UnitOfWork, the Repository and all the operations related to the DB.
The project is referenced in the one where my main application is.
I need this object (UOW) inside the PatientsManagerViewModel
In the first time I created a static property called AppUOW in the constructor of the AppViewModel:
UOW = new OtherProject.UOW(new RepositoryProvider(new RepositoryFactory));
thinking that I could call it from my PatientsManagerViewModel object.
But I think that, since the constructor of the AppViewModel needs a PatientManagerViewModel and this one needs a UOW I can't create a UOW inside the AppViewModel constructor.
So I thought I could make this modification:
[Export(typeof(IOtherProjectUOW))]
public class OtherProjectUOW : IOtherProjectUOW, IDisposable
{
[....]
public OtherProjectUOW()
{
CreateDbcontext();
RepositoryProvider repositoryProvider = new Helper.RepositoryProvider(new RepositoryFactories());
repositoryProvider.DbContext = DbContext;
RepositoryProvider = repositoryProvider;
}
(N.B: this UOW is in another project)...
and the AppViewModel is modified like this:
[Export (typeof(IShell))]
public class AppViewModel : Conductor<object>, IShell, IHandle<ChangeViewEvent>
{
PatientsManagerViewModel patientsManagerVM;
TestManagerViewModel testManagerVM;
MainViewModel mainVM;
public static IOtherProjectUOW UOW { get; private set; }
[ImportingConstructor]
public AppViewModel(IEventAggregator events,
PatientsManagerViewModel pmvm, TestManagerViewModel tmvm,
MainViewModel mvm, IKantaUOW kuow)
{
patientsManagerVM = pmvm;
testManagerVM = tmvm;
mainVM = mvm;
UOW = kuow;
}
But if i try this i received an error in the Bootstrapper class saying that :
--"Could not locate any instances of contract MainApplication.IShell."--
So I'm quite sure the Export - Import system is not working.
Any help is appreciated.

Related

Is it possible to resolve the caller instance in a Ninject factory method via IContext?

I guess this is a very simple scenario that I am trying to achieve.
I am just wondering whether or not it's possible to fetch the calling instance in a Ninject factory method.
public static class Program
{
public static void Main(params string[] args)
{
var standardKernelCaller = new StandardKernelCaller();
standardKernelCaller.Call();
Console.ReadKey();
}
}
public interface IA
{
}
public class A : IA
{
public int Parameter { get; }
public A(int parameter)
{
Parameter = parameter;
}
}
public class Module : NinjectModule
{
public override void Load()
{
Bind<IA>().ToMethod(Create);
}
private static A Create(IContext context)
{
var number = // resolve the caller (StandardKernelCaller) Magic Number using context...
return new A(number);
}
}
public class StandardKernelCaller
{
public const int MagicNumber = 42;
public void Call()
{
var standardKernel = new StandardKernel(new Module());
var stuff = standardKernel.Get<IA>();
}
}
I am not too sure if this is a good practice. At the moment in the related production code I am using something like:
public abstract class BusinessApiController<TBusinessLogic> : ApiController
where TBusinessLogic : class, IBusinessLogic
{
protected TBusinessLogic BusinessLogic { get; private set; }
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
BusinessLogic = CreateBusinessLogic();
}
protected virtual TBusinessLogic CreateBusinessLogic()
{
var businessLogic = BusinessLogicFactory.Create<TBusinessLogic>(this.GetOwinContext());
return businessLogic;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (BusinessLogic != null)
{
BusinessLogic.Dispose();
BusinessLogic = null;
}
}
base.Dispose(disposing);
}
}
public abstract class BusinessController<TBusinessLogic> : Controller
where TBusinessLogic : class, IBusinessLogic
{
protected TBusinessLogic BusinessLogic { get; private set; }
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
BusinessLogic = CreateBusinessLogic();
}
protected virtual TBusinessLogic CreateBusinessLogic()
{
var businessLogic = BusinessLogicFactory.Create<TBusinessLogic>(this.GetOwinContext());
return businessLogic;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (BusinessLogic != null)
{
BusinessLogic.Dispose();
BusinessLogic = null;
}
}
base.Dispose(disposing);
}
}
But I am not a huge fan of the hardcoded "owinContext" parameter name in the factory below:
public static class BusinessLogicFactory
{
// Potentially obsolete readonly / configuration kernel in upcoming Ninject versions
private static readonly StandardKernel StandardKernel = new StandardKernel(new BusinessLogicsNinjectModule());
public static TBusinessLogic Create<TBusinessLogic>(IOwinContext owinContext)
{
// Potential refactoring: get the argument name via expression binding or use Ninject providers
var businessLogic = StandardKernel.Get<TBusinessLogic>(new ConstructorArgument("owinContext", owinContext));
return businessLogic;
}
}
And here is an example of a simplified version of the Ninject module:
public class BusinessLogicsNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IUserManagementBusinessLogic>().To<UserManagementBusinessLogic>();
Bind<IAppointmentManagementBusinessLogic>().To<AppointmentManagementBusinessLogic>();
Bind<ITeamAppointmentManagementBusinessLogic>().To<TeamAppointmentManagementBusinessLogic>();
}
}
By the way if there is a better way of doing for BusinessLogic injection or better design overall, I would love to know more about it.
For know, let me answer your first question:
In your example, it's not possible to determine the instance or the type of StandardKernelCaller from IContext.
If you would inject (ctor-injection, property injection) the value into StandardKernelCaller instead of resolve (Get) it, then you would be gather the type StandardKernelCaller from IContext.
If property-injection would be applied, maybe you could even get the instance of StandardKernelCaller (I suspect it's not available though).
However, you can pass arguments to the Get call: a name (string) for named bindings (resolves to binding registered with the same name, throws if no matching binding available) and IParameter's. IParameters are made available on IContext.
First, use Ninject.Web.Common+Ninject.Web.WebApi extension, so that your controllers don't depend on service locator: https://github.com/ninject/Ninject.Web.Common/wiki
Second, your business logic being dependent on owinContext seems to be a design smell. Separation of concerns should be followed, here it seems you are mixing infrastructure/business layer.
Third, if you really want it, you can pass owinContext trough a method call as a parameter.
Fourth, if you really want it to pass trough a constructor, you can use Ninject.Extensions.Factory:
https://github.com/ninject/Ninject.Extensions.Factory/wiki
public interface IBusinessLogicFactory<TBusinessLogic>
{
TBusinessLogic Create(IOwinContext owinContext);
}
var factory = kernel.Bind<IBusinessLogicFactory<TBusinessLogic>>().ToFactory(() => new TypeMatchingArgumentInheritanceInstanceProvider());
...
var businessLogic = kernel.Get<IBusinessLogicFactory<TBusinessLogic>>().Create(owinContext);

Provide a new object instance in every method of a class?

Lets say I want to use, for example, a new DbContext object whenever a method is called in a class but without getting it by a parameter. Like so
class MyClass {
public virtual void MethodOne() {
// Having automatically a new instance of DbContext
}
public virtual void MethodTwo() {
// Also having automatically a new instance of DbContext
}
}
What I was really hoping for was a DI way of doing this. Like public void Method(IMyWayOfContext context).
class MyClass {
public virtual void MethodOne(IMyWayOfContext context)) {
}
public virtual void MethodTwo(IMyWayOfContext context) {
}
}
Other classes inheriting from this class must be provided with a new instance of dbcontext. That's why I don't want to create a new instance inside of the function
You could do something like this (generic interface, plus a wrapper with multiple constraints):
class DBContext{ }
interface IDoesMethods<TContext> where TContext : new()
{
void MethodOne(TContext context = default(TContext));
void MethodTwo(TContext context = default(TContext));
}
class MyClass : IDoesMethods<DBContext>
{
public void MethodOne(DBContext context)
{
}
public void MethodTwo(DBContext context)
{
}
}
class MyContextWrapper<TClass, TContext> : IDoesMethods<TContext> where TContext : new() where TClass : IDoesMethods<TContext>, new()
{
public void MethodOne(TContext context = default(TContext))
{
instance.MethodOne(new TContext());
}
public void MethodTwo(TContext context = default(TContext))
{
instance.MethodTwo(new TContext());
}
private TClass instance = new TClass();
}
class Program
{
static void Main(string[] args)
{
var wrapper = new MyContextWrapper<MyClass, DBContext>();
wrapper.MethodOne();
wrapper.MethodTwo();
}
}
Make a property with only getter that will return new instance every time
protected DbContext MyDBContext
{
get
{
return new DbContext();
}
}
EDIT: If you want some kind of dependency injection you can make your class generic and pass to instance of the class what type of context you want
class MyClass<T> {
protected DbContext MyDBContext
{
get
{
return Activator.CreateInstance<T>();
}
}
public void MethodOne() {
// Having automatically a new instance of DbContext
}
public void MethodTwo() {
// Also having automatically a new instance of DbContext
}
}
Your simple solution can work this way:
class MyClass {
protected DbContext InternalContext {
return new DbContext();
}
public virtual void MethodOne(DbContext dc = null) {
if(dc == null)
dc = InternalContext;
// do your work
}
public virtual void MethodTwo(DbContext dc = nnull) {
if(dc == null)
dc = InternalContext;
// do your work
}
}
In that case, you have to take care of disposing InternalContext
While answer here looks valid, they don't seem to fulfill perfectly your requirement of having a solution that rely on DI.
DI in it's simplest expression is most of the time achieve with Constructor Injection.
Your design was already good and DI ready.
Indeed, asking for dependencies via the constructor is good.
It is at the composition root of your application that you need to decide what implementation you need to pass.
Using a DI library can help (but it is not required to enable DI).
With your actual class design:
class MyClass {
public virtual void MethodOne(IMyWayOfContextFactory contextFactory)) {
using(var context = contextFactory.Create()){
//play with context
}
}
public virtual void MethodTwo(IMyWayOfContextFactory contextFactory) {
using(var context = contextFactory.Create()){
//play with context
}
}
}
public ContextFactory : IMyWayOfContextFactory {
IMyWayOfContext Create(){
return new MyWayOfContext();
}
}
Without a factory and with a DI container like SimpleInjector, you could have:
class MyClass {
public virtual void MethodOne(IMyWayOfContext context)) {
//play with context
}
public virtual void MethodTwo(IMyWayOfContext context) {
//play with context
}
}
And register your component once at the composition root with configurable Lifestyle management:
container.Register<IMyWayOfContext, MyWayOfContext>(Lifestyle.Transient);
The latter approach is simpler if you want to configure when to inject what instance of your context. Indeed, such configuration is built in an DI Container library. For instance, see: Lifestyle of component with SimpleInjector

How to inject my dbContext with Unity

How do I inject my dbContext class using Unity? I can't just create a Interface like for my other "normal" classes? What should I do with my RequestContext class and what should my UnityConfig look like?
public class RequestContext : IdentityDbContext<User>
{
public RequestContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
Database.SetInitializer<RequestContext>(new CreateDatabaseIfNotExists<RequestContext>());
}
public DbSet<Request> Requests { get; set; }
public DbSet<Record> Records { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
public static RequestContext Create()
{
return new RequestContext();
}
}
In my Repository class i use it like this but want to inject instead:
private RequestContext dbContext;
private IUserRepository _userRepository;
public RequestRepository(IUserRepository userRepository)
{
dbContext = new RequestContext();
_userRepository = userRepository;
}
I'm usually solving this with a DbContextFactory. This would allow you to create the context when needed and also dispose it when you're done.
public interface IDbContextFactory
{
IdentityDbContext<User> GetContext();
}
public class DbContextFactory : IDbContextFactory
{
private readonly IdentityDbContext<User> _context;
public DbContextFactory()
{
_context = new RequestContext("ConnectionStringName");
}
public IdentityDbContext<User> GetContext()
{
return _context;
}
}
This factory can easily be injected. You can see a more complete example here: Repository Pattern universal application
With the factory you will also have the option to create the DbContext in constructor or in the method. When using Unity I recommend you to do as little as possible in the constructor, as Unity will resolve the entire chain for you. This means that the DbContext will be created every time the repository is resolved. This would require the class that injects the repository also needs to dispose the repository (which in turn should dispose the DbContext), and what happens when two classes are using the same repository instance? This can obviously be solved with lifetimemanagers and good programming practices, but I find it more elegant to simply open and close the context when needed.
Example for usage in a method:
using (var context = _dbContextFactory.GenerateContext())
{
return context.Requests.FirstOrDefault(x => x.Id == foo);
}
And a more complete example for your repository:
public class RequestRepository
{
private IDbContextFactory _contextFactory;
public RequestRepository(IDbContextFactory contextFactory)
{
// DbContext will not be created in constructor, and therefore your repository doesn't have to implement IDisposable.
_contextFactory= contextFactory;
}
public Request FindById(int id)
{
// Context will be properly disposed thanks to using.
using (var context = _dbContextFactory.GenerateContext())
{
return context.Requests.FirstOrDefault(x => x.Id == id);
}
}
}
And when you're creating your interface for your context I can also recommend you to change DbSet<T> to IDbSet<T> to allow easier unit testing. Example of interface for DbContext.
public interface IDbContext : IDisposable, IObjectContextAdapter
{
IDbSet<Request> Requests { get; set; }
IDbSet<Record> Records { get; set; }
int SaveChanges();
DbSet Set(Type entityType);
DbSet<TEntity> Set<TEntity>() where TEntity : class;
}
If your're looking to inject the DbContext in the constructor you could also take a look at the Unit of Work-pattern, which wraps the DbContext and allows several classes to use the same context over a specific lifetime (eg a request). One may argue that EF already implements the Unit of Work-pattern, but I leave that discussion for another time. Here's a couple of examples:
http://www.codeproject.com/Articles/741207/Repository-with-Unit-of-Work-IoC-and-Unit-Test
Onion Architecture, Unit of Work and a generic Repository pattern
This site has a GREAT tutorial on how to get Unity working: https://medium.com/aeturnuminc/repository-pattern-with-dependency-injection-mvc-ef-code-first-91344413ba1c
I'm going to assume you have Entity Framework installed, know how to create a viewmodel and put on attributes using System.ComponentModel.DataAnnotations and System.ComponentModel.DataAnnotations.Schema namespaces, and I'll assume you can create a view and controller. None of that is really relevant until the end, anyway.
You have to get the NuGet package Unity to install these references:
Microsoft.Practices.Unity
Unity.Mvc3 (or 4 or 5)
My DataContext (Model1.cs) looks like this:
public partial class Model1 : DbContext
{
public Model1()
: this(true)
{ }
public Model1(bool enableLazyLoading = true)
: base("name=Model1")
{
// You can do this....
//Database.SetInitializer<Model1>(new CreateDatabaseIfNotExists<Model1>());
//this.Configuration.LazyLoadingEnabled = false;
// or this...
Database.SetInitializer<Model1>(null);
this.Configuration.ProxyCreationEnabled = false;
((IObjectContextAdapter)this).ObjectContext.ContextOptions.ProxyCreationEnabled = enableLazyLoading;
((IObjectContextAdapter)this).ObjectContext.ContextOptions.LazyLoadingEnabled = enableLazyLoading;
}
// All my tables and views are assigned to models, here...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
}
My Repository (DataRepository.cs) looks like this:
namespace WeeklyReport.Repository
{
public class DataRepository : IDataRepository
{
private bool disposing;
private readonly Model1 context;
public virtual void Dispose()
{
if (disposing)
{
return;
}
disposing = true;
if (context != null)
{
context.Dispose();
}
}
public void SaveChanges()
{
context.SaveChanges();
}
public DataRepository()
{
context = new Model1();
context.Configuration.ProxyCreationEnabled = false;
}
public IEnumerable<ReportViewModel> GetAllMetrics()
{
var myMetrics = context.MetricsTable; // put into ReportVM and return, etc.
}
// etc., etc.
}
}
My Interface (IDataRepository.cs) looks like this:
namespace WeeklyReport.Repository
{
public interface IDataRepository
{
void SaveChanges();
IEnumerable<ReportViewModel> GetAllMetrics();
}
}
My UnityConfig.cs in the App_Start folder looks like this:
using Microsoft.Practices.Unity;
using WeeklyReport.Repository;
using System.Web.Mvc;
using Unity.Mvc3;
namespace WeeklyReport
{
public class UnityConfig
{
public static void RegisterContainer()
{
var container = new UnityContainer();
//ensure the repository is disposed after each request by using the lifetime manager
container.RegisterType<IDataRepository, DataRepository>(new HierarchicalLifetimeManager());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
}
And you have to call RegisterContainer in Global.ascx.cs inside Application_Start:
UnityConfig.RegisterContainer();
From a controller, it gets a handle to IDataRepository:
using WeeklyReport.Repository;
namespace WeeklyReport.Controllers
{
public class ReportController : Controller
{
private readonly IDataRepository repository;
public ReportController(IDataRepository repository)
{
this.repository = repository;
}
public ActionResult Index()
{
List<ReportViewModel> reportVM = new List<ReportViewModel>();
var reqs = repository.GetAllMetrics();
// iterate reqs and put into reportVM, etc.
return View(reportVM);
}
}
}
And you can call repository as if it was the real class - you're just getting an interface instance to it.
I'm solving this problem with DbContext.Set<TEntity>() method, DbContext wrapper class and generics.
I have IRepositoryContext interface and RepositoryContext to wrap my DbContext:
public interface IRepositoryContext
{
DbContext DbContext { get; }
/// <summary>
/// Commit data.
/// </summary>
void Save();
}
public class RepositoryContext : IRepositoryContext
{
private readonly DbContext _dbContext;
public RepositoryContext(DbContext dbContext)
{
_dbContext = dbContext;
}
public DbContext DbContext { get { return _dbContext; } }
public void Save()
{
_dbContext.SaveChanges();
}
}
Ok, then I write bas implementation of generic repository:
public abstract class RepositoryBase<TEntity, TId> : IRepository<TEntity, TId>
where TEntity : class , IEntity<TId>, IRetrievableEntity<TEntity, TId>
where TId : struct
{
protected readonly IRepositoryContext RepositoryContext;
protected readonly DbContext Context;
protected RepositoryBase(IRepositoryContext repositoryContext)
{
RepositoryContext = repositoryContext;
}
public DbSet<TEntity> Data { get { return RepositoryContext.DbContext.Set<TEntity>(); }
public TEntity Get(TId id)
{
return Data.Find(id);
}
public virtual IList<TEntity> GetAll()
{
return Data.ToList();
}
public virtual TEntity Save(TEntity entity)
{
try
{
var state = entity.Id.Equals(default(TId)) ? EntityState.Added : EntityState.Modified;
RepositoryContext.DbContext.Entry(entity).State = state;
RepositoryContext.Save();
return entity;
}
catch (DbEntityValidationException e)
{
throw ValidationExceptionFactory.GetException(e);
}
}
public virtual void Delete(TEntity entity)
{
if (entity == null) return;
Data.Remove(entity);
Context.SaveChanges();
}
public void Commit()
{
RepositoryContext.Save();
}
public IList<TEntity> Get(Expression<Func<TEntity, bool>> criteria)
{
return Data.Where(criteria).ToList();
}
// some other base stuff here
}
Ok, now I can register my DbContext with next extension methods:
public static class RikropCoreDataUnityExtensions
{
#region Const
private readonly static Type _repositoryInterfaceType = typeof(IRepository<,>);
private readonly static Type _deactivatableRepositoryInterfaceType = typeof(IDeactivatableRepository<,>);
private readonly static Type _deactivatableEntityType = typeof(DeactivatableEntity<>);
private readonly static Type _retrievableEntityType = typeof(IRetrievableEntity<,>);
#endregion Const
#region public methods
/// <summary>
/// Register wrapper class.
/// </summary>
/// <typeparam name="TContext">DbContext type.</typeparam>
/// <param name="container">Unity-container.</param>
public static void RegisterRepositoryContext<TContext>(this IUnityContainer container)
where TContext : DbContext, new()
{
container.RegisterType<IRepositoryContext, RepositoryContext>(new InjectionFactory(c => new RepositoryContext(new TContext())));
}
/// <summary>
/// Register wrapper class.
/// </summary>
/// <typeparam name="TContext">DbContext type.</typeparam>
/// <param name="container">Unity-container.</param>
/// <param name="contextConstructor">DbContext constructor.</param>
/// <param name="connectionString">Connection string name.</param>
public static void RegisterRepositoryContext<TContext>(this IUnityContainer container,
Func<string, TContext> contextConstructor, string connectionString)
where TContext : DbContext
{
container.RegisterType<IRepositoryContext, RepositoryContext>(
new InjectionFactory(c => new RepositoryContext(contextConstructor(connectionString))));
}
/// <summary>
/// Automatically generation and registration for generic repository marked by attribute.
/// </summary>
/// <param name="container">Unity-container.</param>
/// <param name="assembly">Assembly with repositories marked with RepositoryAttribute.</param>
public static void RegisterCustomRepositories(this IUnityContainer container, Assembly assembly)
{
foreach (var repositoryType in assembly.GetTypes().Where(type => type.IsClass))
{
var repositoryAttribute = repositoryType.GetCustomAttribute<RepositoryAttribute>();
if (repositoryAttribute != null)
{
container.RegisterType(
repositoryAttribute.RepositoryInterfaceType,
repositoryType,
new TransientLifetimeManager());
}
}
}
/// <summary>
/// Automatically generation and registration for generic repository for all entities.
/// </summary>
/// <param name="container">Unity-container.</param>
/// <param name="assembly">Assembly with Entities which implements IRetrievableEntity.</param>
public static void RegisterRepositories(this IUnityContainer container, Assembly assembly)
{
foreach (var entityType in assembly.GetTypes().Where(type => type.IsClass))
{
if (!entityType.InheritsFromGeneric(_retrievableEntityType))
continue;
Type[] typeArgs = entityType.GetGenericTypeArguments(_retrievableEntityType);
Type constructedRepositoryInterfaceType = _repositoryInterfaceType.MakeGenericType(typeArgs);
container.RegisterRepository(constructedRepositoryInterfaceType);
if (entityType.InheritsFrom(_deactivatableEntityType.MakeGenericType(new[] { typeArgs[1] })))
{
var constructedDeactivatableRepositoryInterfaceType =
_deactivatableRepositoryInterfaceType.MakeGenericType(typeArgs);
container.RegisterRepository(constructedDeactivatableRepositoryInterfaceType);
}
}
}
#endregion public methods
#region private methods
/// <summary>
/// Generate and register repository.
/// </summary>
/// <param name="container">Unity-container.</param>
/// <param name="repositoryInterfaceType">Repository interface type.</param>
private static void RegisterRepository(this IUnityContainer container, Type repositoryInterfaceType)
{
var factoryGenerator = new RepositoryGenerator();
var concreteFactoryType = factoryGenerator.Generate(repositoryInterfaceType);
container.RegisterType(
repositoryInterfaceType,
new TransientLifetimeManager(),
new InjectionFactory(
c =>
{
var activator = new RepositoryActivator();
return activator.CreateInstance(c, concreteFactoryType);
}));
}
#endregion private methods
}
Finally you can just resolve IRepository<EntityType> on your classes. You just need to register your RepositoryContext:
container.RegisterRepositoryContext<MyDbContext>();
//container.RegisterRepositoryContext(s => new MyDbContext(s), "myConStr");
And your repository will resolve IRepositoryContext and you can have access to DbSet<TEntity> and other DbContext members via IRepositoryContext property.
You can use full source code for repositories, Unity-helpers on Github.

Setting the connection string of a DBContext in my repository class using Ninject

I have an MVC 5 application that uses EF 6 and implements Repository pattern with dependency injection using the DI container Ninject. The connection string for the dbcontext is stored in the Web.config file which the EF Context properly finds. Everything works fine. Lately, I have a requirement that the connection to my DBContext need to be determined at runtime and connect to different databases (but with exactly the same structure). So, I need to change the sql connectionstring part from the entity connectionstring at run-time before the repository is instantiated. I would really appreciate some help in doing it. I am not a DI guru; know just enough Ninject to get my things going.
Here is my Repository Base Interface:
public interface IRepositoryBase<T> where T : class
{
void Add(T entity, string userGuid = "");
void Delete(T entity);
// ... removed other method signatures for brevity
}
My Repository base implementation:
public abstract class RepositoryBase<D, T> : IRepositoryBase<T>, IDisposable
where T : class
where D : DbContext, new()
{
private Guid? currUserGuid = null;
private D dataContext;
protected D DataContext
{
get
{
if (dataContext == null)
dataContext = new D();
return dataContext;
}
set { dataContext = value; }
}
public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate)
{
return DataContext.Set<T>().Where(predicate);
}
public virtual IQueryable<T> GetAll()
{
IQueryable<T> query = DataContext.Set<T>();
return query;
}
public virtual void Delete(T entity)
{
OperationStatus stat = TryDelete(entity);
}
// .... removed rest for brevity
}
Interface and implementation for concrete class:
public interface ICustomerRepository : IRepositoryBase<Customer>
{
Customer GetCustomerAndStatus( Guid custGuid );
}
public class CustomerRepository : RepositoryBase<PCDataEFContext, Customer>, ICustomerRepository
{
public Customer GetCustomerAndStatus( Guid custGuid )
{
return DataContext.Customers.Include( x => x.CustStatusType )
.SingleOrDefault( x => x.PKGuid == custGuid );
}
}
My Ninject dependency resolver:
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver()
{
kernel = new StandardKernel();
AddBindings();
}
public IKernel Kernel { get { return kernel; } }
private void AddBindings()
{
kernel.Bind<ICustomerRepository>().To<CustomerRepository>();
// ... other bindings are omitted for brevity
}
}
and finally, here is my Entity Framework generated DBContext:
public partial class PCDataEFContext : DbContext
{
public PCDataEFContext()
: base("name=PCDataEFContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Customer> Customers { get; set; }
}
All the above code works great! But as I said in the beginning, I don't know how to inject the connection string into my Repositorybase class at runtime so that I don't have to modify any of my inherited repositories (I have plenty of them). Someone please help.
Babu.
Could you do it like this?
public partial class PCDataEFContext : DbContext
{
public PCDataEFContext()
: base(Util.GetTheConnectionString())
{ }
}
public class MyDerivedContext : PCDataEFContext
{
public MyDerivedContext()
: base()
{ }
}
class Util
{
public static string GetTheConnectionString()
{
// return the correct name based on some logic...
return "name=PCDataEFContext";
}
}
Another way of doing it, could be in the RepositorBase class you defined, by altering the connectionstring after the creation of the dbcontext:
protected D DataContext
{
get
{
if (dataContext == null)
{
dataContext = new D();
dataContext.Database.Connection.ConnectionString = "the new connectionstring";
}
return dataContext;
}
set { dataContext = value; }
}

Registering different UnitOfWorks per each module for a generic CommandHandler using structuremap

I'm using CQRS pattern in my recent project, and used EF code first in my DAL, so I defined some generic CommandHandlers to do Insert/Update/Delete:
public class InsertCommandHandler<TEntity> : ICommandHandler<InsertCommandParameter<TEntity>>
where TEntity : BaseEntity, IAggregateRoot<TEntity>, new()
{
private readonly IUnitOfWork _uow;
public InsertCommandHandler(IUnitOfWork uow)
{
_uow = uow;
}
public void Handle(InsertCommandParameter<TEntity> parameter)
{
var entity = parameter.Entity;
_uow.Repository<TEntity>().Add(entity);
}
}
public interface ICommandParameter
{
}
public abstract class BaseEntityCommandParameter<T> : ICommandParameter
where T : BaseEntity, new()
{
public T Entity { get; set; }
protected BaseEntityCommandParameter()
{
Entity = new T();
}
}
public class InsertCommandParameter<T> : BaseEntityCommandParameter<T> where T : class, new()
{
}
As you see I injected the IUnitOfWork to the InsertCommandHandler constructor.
public interface IUnitOfWork : IDisposable
{
IRepository<T> Repository<T>() where T : BaseEntity, IAggregateRoot<T>,new ();
void Commit();
}
I used Structuremap 3 as my IoC Container, So I defined following conversion to resolve ICommandHandlers for each BaseEntity types(using custom registration conventions for partially closed types):
public class CRUDCommandRegistrationConvention : StructureMap.Graph.IRegistrationConvention
{
private static readonly
Type _openHandlerInterfaceType = typeof(ICommandHandler<>);
private static readonly
Type _openInsertCommandType = typeof(InsertCommandParameter<>);
private static readonly
Type _openInsertCommandHandlerType = typeof(InsertCommandHandler<>);
private static readonly
Type _openUpdateCommandType = typeof(UpdateCommandParameter<>);
private static readonly
Type _openUpdateCommandHandlerType = typeof(UpdateCommandHandler<>);
private static readonly
Type _openDeleteCommandType = typeof(DeleteCommandParameter<>);
private static readonly
Type _openDeleteCommandHandlerType = typeof(DeleteCommandHandler<>);
public void Process(Type type, Registry registry)
{
if (!type.IsAbstract && typeof(BaseEntity).IsAssignableFrom(type))
if (type.GetInterfaces()
.Any(x => x.IsGenericType && x.GetGenericTypeDefinition()
== typeof(IAggregateRoot<>)))
{
Type closedInsertCommandType = _openInsertCommandType.MakeGenericType(type);
Type closedInsertCommandHandlerType = _openInsertCommandHandlerType.MakeGenericType(type);
Type closedUpdateCommandType = _openUpdateCommandType.MakeGenericType(type);
Type closedUpdateCommandHandlerType = _openUpdateCommandHandlerType.MakeGenericType(type);
Type closedDeleteCommandType = _openDeleteCommandType.MakeGenericType(type);
Type closedDeleteCommandHandlerType = _openDeleteCommandHandlerType.MakeGenericType(type);
Type insertclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedInsertCommandType);
Type updateclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedUpdateCommandType);
Type deleteclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedDeleteCommandType);
registry.For(insertclosedHandlerInterfaceType).Use(closedInsertCommandHandlerType);
registry.For(updateclosedHandlerInterfaceType).Use(closedUpdateCommandHandlerType);
registry.For(deleteclosedHandlerInterfaceType).Use(closedDeleteCommandHandlerType);
}
}
}
And used it in my CompositionRoot:
public static class ApplicationConfiguration
{
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(s =>
{
s.AssemblyContainingType(typeof(ICommandHandler<>));
s.AssemblyContainingType(typeof(Order));
s.AssemblyContainingType(typeof(FindOrderByIdQueryHandler));
s.WithDefaultConventions();
x.For(typeof(IUnitOfWork))
.Use(typeof(EfUnitOfWork<SaleDBContext>))
.Named("SaleDBContext")
.SetLifecycleTo((Lifecycles.Singleton));
s.Convention<CRUDCommandRegistrationConvention>();
});
});
return ObjectFactory.Container;
}
public static T Resolve<T>()
{
return ObjectFactory.GetInstance<T>();
}
}
I registered EfUnitOfWork<SaleDBContext> for IUnitOfWork, but I want to use separate DbContext per each module in my solution(Bounded context). For example my sale module has its own DbContext, HR module has its own DbContext and etc, and above registration conversion, only register EfUnitOfWork<SaleDBContext> as my IUnitOfWork.
I have some modules(Solution Folders in Visual Studio) in my solution and each module has 3 layer(3 class library projects):
My modules has following structure(each module has 3 assemblies) for example:
SaleModule:
----Application
----Domain (Entities , ...) //Order, Customer,...
----DAL (DbContext ,...) //SaleDbContext
HRModule:
----Application
----Domain (Entities , ...) // Employee, OrganizationUnit, ...
----DAL (DbContext ,...)//HRDbContext
InfrastructureModule:
----Application (ICommandHandler,IQueryHandler,...)
----Domain
----DAL
The InsertCommandHandler<T> puts in Infrastructure Module.
When I use the InsertCommanHandler<T> I want it uses corresponding module's DbContext as IUnitOfWork. for example, I want the InsertCommandHandler<Order> uses SaleDbContext as it's IUnitOfWork and InsertCommandHandler<Employee> uses HRDbContext as it's IUnitOfWork.
[UPDATED]
This is a sample of cunsumers code that IoC containar should provide SaleDbContext for Consumer1 and HRDbContext for Consumer2:
public class Consumer1
{
ICommandHandler<InsertCommandParameter<Order>> _insertCommandHandler;
public Consumer1(ICommandHandler<InsertCommandParameter<Order>> insertCommandHandler)
{
_insertCommandHandler = insertCommandHandler;
}
public void DoInsert()
{
var command = new InsertCommandParameter<Order>();
command.Entity = new Order(){
Number = 'ord-01',
// other properties
};
insertCommandHandler.Handle(command); //this query handler should use SaleDbContext
}
}
public class Consumer2
{
ICommandHandler<InsertCommandParameter<Employee>> _insertCommandHandler;
public Consumer2(ICommandHandler<InsertCommandParameter<Employee>> insertCommandHandler)
{
_insertCommandHandler = insertCommandHandler;
}
public void DoInsert()
{
var command = new InsertCommandParameter<Employee>();
command.Entity = new Employee(){
EmployeeNumber = 'Emp1',
// other properties
};
insertCommandHandler.Handle(command); //this query handler should use HRDbContext
}
}
How could I do that in my composition root using StructureMap?
You can make IUnitOfWork generic as in IUnitOfWork<TConnection>. This allows each Repository to stipulate which UnitOfWork it requires, ideally using constructor injection, e.g.
public class InsertCommandHandler : ICommandHandler<Order>
{
public InsertCommandHandler(IUnitOfWork<SalesDbContext> salesUnitOfWork)
{
// ...
}
}
However, you probably don't want to reference the DbContext in each handler so you should define an abstraction to avoid such a dependency.
Start with a simple interface that all DbContext wrapper classes will implement
public interface IConnection
{
DbContext Context { get; }
}
Update IUnitOfWork accordingly
public interface IUnitOfWork<TConnection> where TConnection : IConnection { }
Here's an example wrapper
public class SalesConnection : IConnection
{
private readonly DbContext context;
public SalesConnection()
{
this.context = new SalesDbContext();
}
public DbContext Context { get { return this.context; } }
}
And here's what the updated command handler will look like
public class InsertCommandHandler : ICommandHandler<Order>
{
public InsertCommandHandler(IUnitOfWork<SalesConnection> salesUnitOfWork)
{
// ...
}
}
UPDATE
The logical thing to do for common handlers is to have one per logical domain (i.e. per DbContext), for example SalesInsertCommandHandler, HRInsertCommandHandler
public class SalesInsertCommandHandler<TCommand> : ICommandHandler<TCommand>
{
public SalesInsertCommandHandler(IUnitOfWork<SalesConnection> unitOfWork)
{
}
}
This adheres to the separation of concerns principle and gives you extra flexibility when you come to decorate your concerns with different aspects (tracing, retry logic etc.)
All command handlers can of course inherit from a single common (abstract) command handler.
public abstract class CommandHandler<TConnection, TCommand> :
ICommandHandler<TCommand>
where TConnection : IConnection
{
private readonly IUnitOfWork<TConnection> unitOfWork;
public CommandHandler(IUnitOfWork<TConnection> unitOfWork)
{
this.unitOfWork = unitOfWork;
}
}
public class SalesInsertCommandHandler<TCommand> :
CommandHandler<SalesConnection, TCommand>
{
}

Categories

Resources