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
Related
I created a simple program as a PoC for an old SharePoint On-Prem project that uses ASP.NET Webforms. In its pages, I have to use property injection, and for everything else, I can use constructor injection. I am also using:
Ninject.Extensions.Factory
Ninject.Extensions.Interception
Ninject.Extensions.Interception.DynamicProxy
Everything was working relatively well until I added interceptors and used Lazy<> to tackle some cyclic dependencies. To simplify this in an example, I've written the following example as a console application:
public class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel(
new NinjectSettings() { LoadExtensions = false },
new DynamicProxyModule(),
new FuncModule());
kernel.Bind<ISomeClass>().To<SomeClass>();
kernel.Bind<IOtherClass>().To<OtherClass>();
kernel.Bind<IAnotherClass>().To<AnotherClass>();
kernel.Intercept(p => true).With(new ClassInterceptor()); // Removing this works, but I need the interceptors.
ISomeClass someClass = kernel.TryGet<ISomeClass>();
someClass.Foo();
}
public interface ISomeClass
{
void Foo();
}
public class SomeClass : ISomeClass
{
[Inject]
public IOtherClass OtherClass { get; set; }
public SomeClass() { }
public void Foo()
{
Console.WriteLine("Foo");
this.OtherClass.Bar();
}
}
public interface IOtherClass
{
void Bar();
}
public class OtherClass : IOtherClass
{
private readonly Lazy<IAnotherClass> _anotherClass;
public IAnotherClass AnotherClass { get { return this._anotherClass.Value; } }
public OtherClass(Lazy<IAnotherClass> anotherClass)
{
this._anotherClass = anotherClass;
}
public void Bar()
{
Console.WriteLine("Bar");
}
}
public interface IAnotherClass
{
void FooBar();
}
public class AnotherClass : IAnotherClass
{
private readonly Lazy<IOtherClass> _otherClass;
public IOtherClass OtherClass { get { return this._otherClass.Value; } }
public AnotherClass(Lazy<IOtherClass> otherClass)
{
this._otherClass = otherClass;
}
public void FooBar()
{
Console.WriteLine("FooBar");
this.OtherClass.Bar();
}
}
public class ClassInterceptor: SimpleInterceptor
{
public ClassInterceptor() { }
protected override void BeforeInvoke(IInvocation invocation)
{
base.BeforeInvoke(invocation);
Console.WriteLine("I'm doing stuff before.");
}
protected override void AfterInvoke(IInvocation invocation)
{
base.BeforeInvoke(invocation);
Console.WriteLine("I'm doing stuff after.");
}
}
}
As a result, I am getting the following error:
Unhandled Exception: System.TypeLoadException: Could not load type 'Castle.Proxies.Func`2Proxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=a621a9e7e5c32e69' because the parent type is sealed.
If I remove the "Lazy<>", it will re-introduce cyclic dependencies. If I remove interception, it will not have any errors, but I need the interceptors. And, I have to use property injection on the pages because the constructors of the pages are managed by webforms with no helpful hooks like there are in MVC land. NOTE: webforms are being used because SharePoint 2013 is being used.
Any ideas how to keep both interception and Lazy<> declarations without encountering the error above?
I was able to resolve this by not adding the interceptors to the entire kernel as there were some types that could not have proxies created for them. Considering the exclusions lists were probably more than I was encountering, I chose the next best option which was to apply global interceptors individually to each binding:
static void Main(string[] args)
{
IKernel kernel = new StandardKernel(
new NinjectSettings() { LoadExtensions = false },
new DynamicProxyModule(),
new FuncModule());
AddInterceptors(kernel.Bind<ISomeClass>().To<SomeClass>());
AddInterceptors(kernel.Bind<IOtherClass>().To<OtherClass>());
AddInterceptors(kernel.Bind<IAnotherClass>().To<AnotherClass>());
//kernel.Intercept(p => true).With(new ClassInterceptor());
ISomeClass someClass = kernel.TryGet<ISomeClass>();
someClass.Foo();
}
private static void AddInterceptors<T>(IBindingWhenInNamedWithOrOnSyntax<T> binding)
{
binding.Intercept(p => true).With(new ClassInterceptor());
/* ... other interceptors ... */
}
Thanks for letting me know what was going with the interception extension trying to create a proxy for Lazy and T, #BatteryBackupUnit.
Any better solutions are welcomed!
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);
Is it possible to limit object creation to methods of specific class?
For exemple: I have a class Transaction, and I would like to limit it object creation to methods of any class that inherits from AbstractService or IService:
Allowed Scenario:
public class ServiceA : AbstractService (or IService)
{
public void MethodA()
{
var transaction = new Transaction();
}
public void MethodB()
{
var transaction = new Transaction();
}
}
Prohibited Scenario:
public class ServiceB
{
public void MethodA()
{
var transaction = new Transaction(); // cannot create
}
public void MethodB()
{
var transaction = new Transaction(); // cannot create
}
}
There is a access modifier or something else that I can mount that scenarios?
There is a access modifier or something else that I can mount that scenarios?
Yes there is something else that can "mount" that scenario, but it's a lot of work and abstraction for, in my opinion, very little reward. This requires returning an interface of the Transaction, not a concrete type. (I'm pretty sure this works, I haven't compiled it however).
public abstract class AbstractService
{
}
public interface IService
{
}
public interface ITransaction
{
}
public static class TransactionFactory
{
// created them as extensions, but you could remove *this*
public static ITransaction CreateTransaction(this AbstractService instance)
{
return new Transaction ();
}
public static ITransaction CreateTransaction(this IService instance)
{
return new Transaction ();
}
private class Transaction : ITransaction
{
public Transaction ()
{
}
}
}
As a side note, someone technically could pass in null, so it would be best to do additional checking of the method parameters (however, that would be a runtime issue instead of a compile time issue).
If you wanted compile time checking I think you could do...
public interface ITransactionFactory { }
public abstract class AbstractService : ITransactionFactory { }
public interface IService : ITransactionFactory { }
public static class TransactionFactory<T>
where T : ITransactionFactory
{
public static ITransaction CreateTransaction(this T instance)
{
return new Transaction ();
}
// ....
Not quite sure if the second one works
The short answer is no, there is no access modifier which says "This object can only be constructed from a class which implements a specific interface".
You could code your way round this limitation, but its far from clean/foolproof.
public class Transaction
{
private Transaction(){} // private important!
public static Transaction Create(object creator)
{
if(creator is IService)
return new Transaction();
throw new InvalidOperationException();
}
}
public class ServiceA : IService
{
public void MethodA()
{
var transaction = Transaction.Create(this); // works
}
}
public class ServiceB
{
public void MethodA()
{
var transaction = Transaction.Create(this); // fails
}
}
It should be obvious how easily circumventable the above is. I suspect you have an XY Problem and you think this was the way to solve it.
Maybe I'm misunderstanding what you're trying to do, but it seems like this should do the trick:
public abstract class AbstractService : IService
{
protected class Transaction
{
}
}
public class ServiceA : AbstractService
{
public void MethodA()
{
var transaction = new Transaction();
}
public void MethodB()
{
var transaction = new Transaction();
}
}
public class ServiceB
{
public void MethodA()
{
var transaction = new Transaction(); // cannot create
}
public void MethodB()
{
var transaction = new Transaction(); // cannot create
}
}
internal interface IService
{
}
If you want anyone else to be able to use the Transaction, you'll need to have it implement some public interface or inherit it from another public class, but you can now ensure that no one else can create a Transaction object.
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>
{
}
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.