I use MEF to map interface to implementation class as a way of DI. For example, I use the Import attribute for an interface, and Export for implementation class. My understanding is that the MEF framework will create the implementation class instances and hold them in MEF's container for use or auto-injection.
Some of my implementation classes implement IDispose interface. Since instances are created by MEF, I think I should let the MEF to call components' Dispose method if they are disposable when the MEF is out. For example, in my application, I hold a reference to the MEF's container. When the application terminates, I call the Dispose method of the container. The problem is that my components' Dispose is never called.
Here are some example codes about the import and export mapping:
[Import]
private IMyInterface IComponent1 { get; set; }
....
[Export]
private IMyInterface Component {
get {
var instance = new MyImplemetation();
....
return instance;
}
}
....
There many other import and export definitions for other mappings in the similar way. I construct mappings in this way so that the MEF has the knowledge of the relationships and the way how to create the mapped instances. Here are some codes in my application to load mappings by using AssemblyCatalog:
var catalog = new AggregateCatalog();
catalog.Add (new AssemblyCatalog(Assembly.GetExecutingAssembly());
var batch = new CompositionBatch();
batch.AddPart(catalog);
// MEF container has all the mappings
var container = new CompositionContainer(catalog);
....
// Get instance from container
var instance = container.GetExportedValue<IMyInterface>();
// my instance CTOR has a contructor with several other
// implementation instances injected by interface
// instance starts to do its job and coordinates others ...
instance.Start();
....
// Finally the job is done.
// Dispose the container explicitly there.
container.Dispose();
// But my components are never disposed
// this results some connections not being closed
// file streams not being closed...
Here the instance has many other components injected through CTOR by the MEF. Those components also contain other components which are injected by the MEF. The problem is that it is really hard to make decision when to dispose components since some instances are shared. If I called Dispose on one, this would cause others not being able to use it. As you can see in this picture, instances are created by the MEF and injected to my application classes. Each component should not have any knowledge of others, and it should use injected components to do the job.
I am not sure where/how I should instruct the MEF to call Dispose on components when the application terminates or the container is disposed? Should I call the Dispose on components? I don't think that is right since the MEF creates them and inject them into clients as required. The clients should not call their Dispose when finishing their jobs.
MEF does manage the lifetime of the components it creates. It looks like the problem in your example is that the object you want disposed is not actually created by MEF. Perhaps you want to do something like this:
public class ComponentExporter : IDisposable
{
private IMyInterface _component;
[Export]
public IMyInterface Component
{
get
{
if (_component != null)
{
_component = new MyImplementation();
// ...
}
return _component;
}
}
public void Dispose()
{
if (_component != null)
{
_component.Dispose();
}
}
}
ComponentExporter is the class actually created by MEF, and if it implements IDisposable then MEF will dispose it with the container. In this example ComponentExporter disposes the created component when it is dispose, which is likely what you want.
Of course it would be easier if you just put the export on the MyImplementation class directly. I assume you have some reason for not doing that, but this is how it would look:
[Export(typeof(IMyInterface))]
public class MyImplementation : IMyInterface, IDisposable
{
// ...
}
A few other notes on your code: You probably don't need to add the catalog to the container via the batch, unless you are importing it somewhere and modifying it from parts inside the container. And if you happen to be processing many requests and are concerned about performance, you should only create the AssemblyCatalog once, and then use the same one for all requests.
Daniel is right. I defined a relationships of Import and Export as properties in my mapping classes. I loaded them as ComposablePartCatalog to MEF's container so that MEF can magically fetches corresponding instances on fly. It is within the mapping classes that I have some codes to new instances. Therefore, I have to find a way to let MEF to call back to those mapping classes to dispose the created resources when MEF is out of a process.
I like Daniel's suggestion to introduce a class for my Export part. Since all my DI mappings are defined in the way of properties (getter and setters), I created a base class like this:
public class ComponentExporterBase: IDisposable {
private List<IDisposable> _list;
public ComponentExporterBase() {
_list = new List<IDisposable>();
}
protect void Add(IDisposable obj) {
_list.Add(obj);
}
protected virtual void Dispose(bool disposing) {
if (disposing) {
foreach(var obj in _list) {
obj.Dispose();
}
_list.Clear();
}
}
public void Dispose() {
Dispose(true);
}
}
With this base class, my mapping classes will be able to let MEF to do the disposing job. For example, here is one example:
internal class MyDIMappingClass : ComponentExporterBase {
[Import]
private IDataReader _dataReader { get; set; }
[Export]
private IController {
get {
var reader = _dataReader;
var instance = new MyMainController(reader);
base.Add(instance);
return instance;
}
...
}
All my mapping classes are defined in the similar way, and they are much cleaner. The basic principle is that instances or resources which are created within a class should be disposed within the class, but not injected instances. In this way, I don't need to clean up any injected instances by MEF any more, as in this example:
public class MyMainController : IController {
private IDataReader _dataReader;
// dataReader is injected through CTOR
public MyMainControler(IDataReader dataReader) {
_dataReader = dataReader;
...
}
...
public void Dispose() {
// dispose only resources created in this class
// _dataReader is not disposed here or within the class!
...}
}
By the way, I like to use properties as my imports and exports since the attributes have nothing to do a class' business logic. In other many cases, some classes are from third parties and I don't have access to their source codes to mark them as export.
Related
My question based on InventorySampleApp by Microsoft.
The ServiceLocator contains method Configure() that register Services and ViewModels. With method GetService<T>() we can get it. For example, ProductView.cs:
ViewModel = ServiceLocator.Current.GetService<ProductDetailsViewModel>();
Each *ViewModel contains constructor with interface, for example:
public ProductDetailsViewModel(IProductService productService, IFilePickerService filePickerService, ICommonServices commonServices)
I can't understand the magiс that ViewModel uses to get such interfaces into its constructor. So there are no lines like this:
... = new ProductDetailsViewModel(productService, filePickerService, commonServices)
How does the ViewModel constructor get the required interfaces?
ServiceLocator
public class ServiceLocator : IDisposable
{
static private readonly ConcurrentDictionary<int, ServiceLocator> _serviceLocators = new ConcurrentDictionary<int, ServiceLocator>();
static private ServiceProvider _rootServiceProvider = null;
static public void Configure(IServiceCollection serviceCollection)
{
serviceCollection.AddSingleton<ISettingsService, SettingsService>();
serviceCollection.AddSingleton<IDataServiceFactory, DataServiceFactory>();
serviceCollection.AddSingleton<ILookupTables, LookupTables>();
serviceCollection.AddSingleton<ICustomerService, CustomerService>();
serviceCollection.AddSingleton<IOrderService, OrderService>();
serviceCollection.AddSingleton<IOrderItemService, OrderItemService>();
serviceCollection.AddSingleton<IProductService, ProductService>();
serviceCollection.AddSingleton<IMessageService, MessageService>();
serviceCollection.AddSingleton<ILogService, LogService>();
serviceCollection.AddSingleton<IDialogService, DialogService>();
serviceCollection.AddSingleton<IFilePickerService, FilePickerService>();
serviceCollection.AddSingleton<ILoginService, LoginService>();
serviceCollection.AddScoped<IContextService, ContextService>();
serviceCollection.AddScoped<INavigationService, NavigationService>();
serviceCollection.AddScoped<ICommonServices, CommonServices>();
serviceCollection.AddTransient<LoginViewModel>();
serviceCollection.AddTransient<ShellViewModel>();
serviceCollection.AddTransient<MainShellViewModel>();
serviceCollection.AddTransient<DashboardViewModel>();
serviceCollection.AddTransient<CustomersViewModel>();
serviceCollection.AddTransient<CustomerDetailsViewModel>();
serviceCollection.AddTransient<OrdersViewModel>();
serviceCollection.AddTransient<OrderDetailsViewModel>();
serviceCollection.AddTransient<OrderDetailsWithItemsViewModel>();
serviceCollection.AddTransient<OrderItemsViewModel>();
serviceCollection.AddTransient<OrderItemDetailsViewModel>();
serviceCollection.AddTransient<ProductsViewModel>();
serviceCollection.AddTransient<ProductDetailsViewModel>();
serviceCollection.AddTransient<AppLogsViewModel>();
serviceCollection.AddTransient<SettingsViewModel>();
serviceCollection.AddTransient<ValidateConnectionViewModel>();
serviceCollection.AddTransient<CreateDatabaseViewModel>();
_rootServiceProvider = serviceCollection.BuildServiceProvider();
}
static public ServiceLocator Current
{
get
{
int currentViewId = ApplicationView.GetForCurrentView().Id;
return _serviceLocators.GetOrAdd(currentViewId, key => new ServiceLocator());
}
}
static public void DisposeCurrent()
{
int currentViewId = ApplicationView.GetForCurrentView().Id;
if (_serviceLocators.TryRemove(currentViewId, out ServiceLocator current))
{
current.Dispose();
}
}
private IServiceScope _serviceScope = null;
private ServiceLocator()
{
_serviceScope = _rootServiceProvider.CreateScope();
}
public T GetService<T>()
{
return GetService<T>(true);
}
public T GetService<T>(bool isRequired)
{
if (isRequired)
{
return _serviceScope.ServiceProvider.GetRequiredService<T>();
}
return _serviceScope.ServiceProvider.GetService<T>();
}
#region Dispose
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_serviceScope != null)
{
_serviceScope.Dispose();
}
}
}
#endregion
When using dependency injection, the instantiation of objects is moved to a component called Dependency Injection (DI) Container or Inverse of Control (IoC) Container. This component has some kind of registry that contains all known services that can be instantiated. In your example, the serviceCollection is that registry.
Now, whenever a component A needs an instance from the registry, there are two different options:
Directly ask the container for an instance, e. g. ServiceLocator.Current.GetService<ProductDetailsViewModel>(). This is known as the Service Locator Pattern (I'd recommend to forget this immediately).
Rather than asking the container directly, request the dependency via constructor of A (e. g. public A(ProductDetailsViewModel viewModel)).
The second approach can be pushed more and more upwards until the top of the application hierarchy is reached - the so called composition root.
Anyways, in both ways, the container uses the mechanism of Reflection. It is a way of retrieving metadata of classes, methods, properties, constructors, etc. Whenever the container is asked for a certain type (e. g. ProductDetailsViewModel), he uses reflection to get information about its constructor.
Once the constructor is resolved, its dependencies are known as well (IProductService, IFilePickerService, ICommonServices). Since these dependencies are registered within the container (remember the serviceCollection), instances can be created.
This goes on and on until there are no more dependencies and the container can start instantiating and composing all the objects. Finally, there is an instance of ProductDetailsViewModel.
If there is one dependency within the construction chain that is unknown to the container, the instantiation fails.
So basically, the process of instantiation is moved away from your code into the DI container.
Notice that the GetService method calls into ServiceProvider.GetService. This is a library method that takes care of things for you. Underneath the covers, it uses reflection to examine the constructor of the type you request.
For example, when you request a ProductDetailsViewModel, the ServiceLocator can see that it needs object of the types IProductService, IFilePickerService, ICommonServices.
It then looks into its registry of services. For example, the line
serviceCollection.AddSingleton<IProductService, ProductService>();
registers the concrete type ProductService against the interface IProductService, so whenever the ServiceLocator needs to create an IProductService object, it'll use a ProductService object.
This process is called auto-wiring and is described in more details in chapter 12 of Steven van Deursen's and my book about Dependency Injection.
I can't understand the magiс that ViewModel uses to get such interfaces into its constructor.
Indeed, do yourself the favour and learn Pure DI instead of relying on opaque libraries that you don't feel comfortable with.
I've never seen that example code base before, but from the examples posted here, it looks like it's filled with code smells and anti-patterns.
I have an application with client, Library and Interface as a middle layer. The classes in the Library implement the Interface.I want to call the library without having to reference it. So I dont have to do this:
IInterface myClass = new Library.MyClass();
One way is to use Unity I guess. Is there any other way? Somehow the whole idea of the Interface fades away right now.
Thanks
There are a couple of ways you can do this.
One, through the use of Dependency Inversion, as you show with Unity, and the other by writing class factories, and lastly, as you've mentioned, newing up the class instance, which is not really helpful at all :)
My own personal taste tends to Dependency Inversion, where Structuremap is my favourite IoC Container. Very easy to set up, and very easy to use, but most of the IoC Containers are very well documented.
The thing you typically end up with are something to the likes of:
IInterface myClass = myContainer.GetInstanceOf<IInterface>();
If I am right, the library is not a third party component and you can change the implementation!? If so, i would suggest to use MEF. It is part of the .Net framework and supports exactly what you want - loading components from other assemblies that are not necessarily referenced.
In your library, you have to declare the class to use in you app with an export attribute:
[Export(typeof(IInterface))] class MyClass : IInterface{ }
And in your client application, you can import the component with:
[Import(typeof(IInterface))] public IInterface myClase;
And finally you can compose all imports and exports:
var catalog = new AggregateCatalog();
// add assamby by type
catalog.Catalogs.Add(new AssemblyCatalog(typeof (AnyType).Assembly));
// add assembly by path
// this example adds all assembly in the current directory that ends with "Extension.dll".
catalog.Catalogs.Add(new DirectoryCatalog(#".", "*Extensions.dll"));
var container = new CompositionContainer(catalog);
// compose parts: MEF composes all imports and exports
container.ComposeParts(this);
It is usually being done by using Factory design pattern.
public interface IMyInterface
{
}
public class A : IMyInterface
{
internal A() // so, the user/developer won't be able to call "var a = new A()" outside of the scope of the assembly
{
}
}
public class B : IMyInterface
{
internal B()
{
}
}
public static class MyFactory
{
public static IMyInterface CreateA()
{
return new A();
}
public static IMyInterface CreateB()
{
return new B();
}
}
usage:
static void Main()
{
IMyInterface a = MyFactory.CreateA(); // instance of A
IMyInterface b = MyFactory.CreateB(); // instance of B
}
If you are creating an API, you can set the constructor of A and B to internal, so the developer won't be able to create an instance of them without using the Factory.
Note: you can use the factory to store the created instance, so it will return the same instance rather then creating a new one every single time.
So we have ran into what seems like a very common issue with StructureMap and IoC containers in general I assume. Bidirectiona/Circuar dependencies.
Given the following code, it is currently causing a circular dependency since we have it 'autowiring' properties.
public class ServiceA:IServiceA
{
public IServiceB ServiceBDependency {get;set;}
}
public class ServiceB:IServiceB
{
public IServiceA ServiceADependency {get;set;}
}
I see the 'dependency' of each of these on eachother, however, I feel that as a property, they are not true dependencies which is what separates them from using constructor injection.
It seems that there should be a way for these services to be resolved...and then have the properties injected after the objects have been created?
I know of various ways to get around this, including the true clean way of rearchitecting my services, but i am curious as to what options I have with instantiation and service registration with StructureMap. It seems like a fairly common issue that would need a solution.
I'd like to show you my approach. I am using only the setter injection. And we often have many objcets referencing each other, in our web app. E.g. IUserFacade requires IUserState on user creation while IUserState requires IUserFacade on userState deletion (to check for constraint).
e.g.:
public interface IUserFacade
{
... // User facade Add, Update, Delete
IUserStateFacade { set; }
}
public interface IUserStateFacade
{
...
IUserFacade { set; }
}
In reality, we have many objects with cross references, and even more complicated. And it would really be very costy, if all the referenced objects should be created each time, even if not used during the request. We need the "lazy", the proxy objects to be placed in the setters.
The way how to do it, is a mix of the: 1) StructureMap (IoC top) and 2) Castle (proxying top) libraries. Below I will show some snippets of objects needed for this solution. More could be found inside open source project Catharsis
Wrapper. This object would be injected into each Property by SM (StructureMap) instead of real implementor. It is the sleeping implementation. It is waiting for a first call. If it will never happen (IUserFacade is deleting user, no need to access referenced IUserStateFacade during such request) this wrapper will sleep for ever (request). Once touched, SM will create the real object and Wrapper will pass all calls to that.
The Castle interceptor:
public class Wrapper : IInterceptor
{
object _lazy;
protected readonly Type Type;
public Wrapper(Type type)
{
Type = type;
}
public void Intercept(IInvocation invocation)
{
if (_lazy.IsNull()) // lazily instantiate the instance
{
_lazy = ObjectFactory.GetInstance(Type);
}
try
{
var method = invocation.Method;
if (method.ContainsGenericParameters)
{
method = method.MakeGenericMethod(invocation.GenericArguments);
}
invocation.ReturnValue = method.Invoke(_lazy, invocation.Arguments);
}
catch (TargetInvocationException ex)
{
// PublishingManager.Publish(.... // publish exception
throw;
}
}
}
ProxyInstance. Now, we need an object, clear and understandable to SM. That object will be mapped to all interfaces (IUserFacade...) Instead of returning implementation of the UserFacade.
We can also use our custom AOP filters here.
This ProxyInstance will be provided with the real implementor type, and building up the Wrapper.
The StructureMap Instance:
public class ProxyInstance : Instance
{
protected readonly ProxyGenerator Factory = new ProxyGenerator();
protected readonly Type ConcreteType;
public ProxyInstance(Type type)
{
ConcreteType = type; // the type for our Wrapper, the real implementation
}
protected override object build(Type pluginType, BuildSession session)
{
var aopFilters =
// my custom way how to inject more AOP filters
AopFilterManager.GetFilters()
// the core for us, one of the interceptors is our Wrapper
.Union(new[] { new Wrapper(ConcreteType) })
.ToArray();
// Castle will emit a proxy for us, but the Wrapper will do the job
var proxy = Factory
.CreateClassProxy(ConcreteType, AopFilterManager.AopOptions, aopFilters);
return proxy;
}
And now just use some standard way how to map it in the SM (I am using custom ProxyConvention but it is out of the scope here). Let's use simplified explicit mapping:
registry
.For<IUserFacade>()
.HybridHttpOrThreadLocalScoped()
.Use(new ProxyInstance(typeof(UserFacade)));
...
Also, each of our objects created via SM, implements IService. So, the default setter injection could be set like this:
registry.SetAllProperties
(
set => set.TypeMatches
(
type => type
.GetInterfaces()
.Any(i => i.IsEquivalentTo(typeof(IService)))
)
);
From that moment, when we need to work with a IUserFacade (the direct ObjectFactory call, or accessed via Wrapper), we recieve the real implementor. All its properties (setter injection) will be pre-populated with our ProxyInstance / Wrapper.
If any of these properties is accessed, e.g. IUserStateFacade the same (discribed above for IUserFacade) will happen again.
Because the Lifecycle is Thread or Request based, we have only one implementor in runtime/web request
Because we do inject the Wrappers while using setter injection, no issues with circular infinite loops. Only the first level is injected each time
I'm trying to remove a Service Locator from an abstract base class, but I'm not sure what to replace it with. Here is a psuedo-example of what I've got:
public abstract class MyController : Controller
{
protected IKernel kernel;
public MyController(IKernel kernel) { this.kernel = kernel); }
protected void DoActions(Type[] types)
{
MySpecialResolver resolver = new MySpecialResolver(kernel);
foreach(var type in types)
{
IMyServiceInterface instance = resolver.Get(type);
instance.DoAction();
}
}
}
The problem with this is that the instanciator of a derived class doesn't know what bindings the kernel must have in order to keep MySpecialResolver from throwing an exception.
This might be intrinsicly intractable because I don't know from here which types I'll have to resolve. The derived classes are responsible for creating the types parameter, but they aren't hardcoded anywhere. (The types are based on the presence of attributes deep within the derived class's composition hierarchy.)
I've trying to fix this with lazy loading delegates, but so far I haven't come up with a clean solution.
Update
There are really two issues here, one is that the IoC container is passed to the controller, acting as a service locator. This is easy to remove--you can move the location up or down the call stack using all sorts of techniques.
The second issue is the difficult one, how can you ensure that the controller has the necessary services when the requirements aren't exposed until runtime. It should have been obvious from the start: you can't! You will always be dependent upon either the state of the service locator or contents of a collection. In this particular case no amount of fiddling will ever resolve the problem described in this article with staticly typed dependencies. I think that what I'm going to end up doing is passing a Lazy array into the controller constructor and throwing an exception if a required dependency is missing.
I agree with #chrisichris and #Mark Seemann.
Ditch the kernel from the controller. I'd switch your resolver composition a little bit so that your controller can remove the dependency on the IoC container and allow the resolver to be the only item that worries about the IoC container.
Then I would let the resolver get passed into the constructor of the controller. This will allow your controller to be far more testable.
For example:
public interface IMyServiceResolver
{
List<IMyServiceInterface> Resolve(Type[] types);
}
public class NinjectMyServiceResolver : IMyServiceResolver
{
private IKernal container = null;
public NinjectMyServiceResolver(IKernal container)
{
this.container = container;
}
public List<IMyServiceInterface> Resolve(Type[] types)
{
List<IMyServiceInterface> services = new List<IMyServiceInterface>();
foreach(var type in types)
{
IMyServiceInterface instance = container.Get(type);
services.Add(instance);
}
return services;
}
}
public abstract class MyController : Controller
{
private IMyServiceResolver resolver = null;
public MyController(IMyServiceResolver resolver)
{
this.resolver = resolver;
}
protected void DoActions(Type[] types)
{
var services = resolver.Resolve(types);
foreach(var service in services)
{
service.DoAction();
}
}
}
Now your controller isn't coupled to a specific IoC container. Also your controller is much more testable since you can mock the resolvers and not require an IoC container at all for your tests.
Alternatively, if you don't get to control when a controller is instantiated, you can modify it slightly:
public abstract class MyController : Controller
{
private static IMyServiceResolver resolver = null;
public static InitializeResolver(IMyServiceResolver resolver)
{
MyController.resolver = resolver;
}
public MyController()
{
// Now we support a default constructor
// since maybe someone else is instantiating this type
// that we don't control.
}
protected void DoActions(Type[] types)
{
var services = resolver.Resolve(types);
foreach(var service in services)
{
service.DoAction();
}
}
}
You would then call this at your application start up to initialize the resolver:
MyController.InitializeResolver(new NinjectMyServiceResolver(kernal));
We did this to handle elements created in XAML who require dependencies resolved but we wanted to remove Service Locator like requests.
Please excuse any syntactical errors :)
I'm writing a blog post series on the topic of refactoring an MVVM application with Service Locator calls in the view models you might find interesting. Part 2 is coming soon :)
http://kellabyte.com/2011/07/24/refactoring-to-improve-maintainability-and-blendability-using-ioc-part-1-view-models/
Maybe you should just do away the Kernel, Types and MySpecialResolver and let the subclasses call DoActions with the IMyServiceInterface instances they need as argument directly. And let the subclasses decide how they get to these instances - they should know best (or in case they don't know which exactly the one who ever decides which instances of IMyServiceInterface are needed)
I would have liked to have a bit more information before posting this answer, but Kelly put me on the spot. :) Telling me to put my code where my mouth is, so to speak.
Like I said in my comment to Kelly, I disagree with moving the resolver/locator from a static implementation to an injected implementation. I agree with ChrisChris that the dependencies the derived type needs should be resolved in that class and not delegated to the base class.
That said, here is how I would remove the service location...
Create Command Interface
First of all I would create a command interface for the specific implementation. In this case the types sent with the DoActions method are generated from attributes, so I would create an IAttributeCommand. I am adding a Matches method to the command in order to declare the command for use by certain types.
public interface IAttributeCommand
{
bool Matches(Type type);
void Execute();
}
Add Command Implementations
To implement the interface, I pass in the specific dependencies I need to execute my command (to be resolved by my container). I add a predicate to my Matches method, and define my Execute behavior.
public class MyTypeAttributeCommand : IAttributeCommand
{
MyDependency dependency;
SomeOtherDependency otherDependency;
public MyTypeAttributeCommand (MyDependency dependency, ISomeOtherDependency otherDependency)
{
this.dependency = dependency;
this.otherDependency = otherDependency
}
public bool Matches(Type type)
{
return type==typeof(MyType)
}
public void Execute()
{
// do action using dependency/dependencies
}
}
Register Commands with Container
In StructureMap (use your favorite container), I would register the array like so:
Scan(s=>
{
s.AssembliesFromApplicationBaseDirectory();
s.AddAllTypesOf<IAttributeCommand>();
s.WithDefaultConventions();
}
Select and Execute Commands Based on Type
Finally, on the base class, I define an IAttributeCommand array in my constructor arguments to be injected by the IOC container. When the derived type passes in the types array, I will execute the correct command based on the predicate.
public abstract class MyController : Controller
{
protected IAttributeCommand[] commands;
public MyController(IAttributeCommand[] commands) { this.commands = commands); }
protected void DoActions(Type[] types)
{
foreach(var type in types)
{
var command = commands.FirstOrDefault(x=>x.Matches(type));
if (command==null) continue;
command.Execute();
}
}
}
If you multiple commands can handle one type, you can change the implementation: commands.Where(x=>x.Matches(type)).ToList().ForEach(Execute);
The effect is the same, but there is a subtle difference in how the class is constructed. The class has no coupling to an IOC container and there is no service location. The implementation is more testable as the class can be constructed with its real dependencies, with no need to wire up a container/resolver.
Suppose that your code is properly designed for DI and IOC through constructor injection of any dependencies. Then whether an IOC container or DI-by-hand is used or not at the composition root doesn't matter much for this problem. I think.
Anyway, I find myself over and over again in a mental struggle with how I should best deal with scope-based services, like transactions or other obviously transient operations. There are constraints that I want to abide to:
Don't let dependency interfaces be IDisposable - it's a leaky abstraction that only the actual implementing type (and the fiddler sitting at the composition root) should care about.
Don't use static service locator types deep down the graph to resolve a dependency - only inject and resolve through the constructor.
Don't pass the IOC container, if any, as a dependency down the graph.
To be able to use using, we need IDisposable, but since a dependency interface shouldn't be IDisposable, how do you get around it to get scoped behavior?
In cases like this I would inject a service factory that creates those scoped services and let the service interface derive from IDisposable. This way the factory would be responsible to create the appropriate service instances and the only point that decides which service implementation to return. You would not need to inject the scoped service anywhere.
public interface ITransaction : IDisposable
{
}
public interface ITransactionFactory
{
ITransaction CreateTransaction();
}
public class Foo
{
private readonly ITransactionFactory transactionFactory;
public Foo(ITransactionFactory transactionFactory)
{
this.transactionFactory = transactionFactory;
}
public void DoSomethingWithinTransaction()
{
using(ITransaction transaction = this.transactionFactory.CreateTransaction())
{
DoSomething();
}
}
}
Most IoC containers today have substantial built-in support for units of work of this nature.
In Autofac, the mechanism that best fits your requirements is the Owned<T> relationship type. You can see it in action (and get some more material) via this article.
Hope this helps,
Nick
Roll your own "garbage collector" maybe? Something that periodically checks IsComplete and/or an LastAccessed attribute of a Dictionary<Transaction> and wastes the "old" ones. It's "a walking memory leak" but either you clean-up explicitly (like through IDisposable) or you workout how to clean-up automatically.
There may be an AOP solution to kicking-off the "gc"... a commit/rollback sounds like a good place to cut... and maybe you won't even need a GC at all... just cleanup the transaction on the way back-up the callstack from commit or rollback.
Good luck with it. I'll be interested to see what solutions (and ideas) other people come-up with.
Cheers. Keith.
I guess another alternative you could use is to wrap your instances with a disposable type, that way it could automatically handle the disposal of the type regardless of whether the type is actually disposable. E.g, I could define something like:
public class DisposableWrapper<T> : IDisposable
{
private readonly T _instance;
private readonly IDisposable _disposable;
public DisposableWrapper(T instance)
{
_instance = instance;
_disposable = instance as IDisposable;
}
public void Dispose()
{
if (_disposable != null)
_disposable.Dispose();
}
public static implicit operator T(DisposableWrapper<T> disposableWrapper)
{
return disposableWrapper._instance;
}
}
(Hopefully with a bit more error handling!)
Given that I know at the point of disposal whether the type is disposable, I can call it accordingly. I can also provide an implicit operator to cast back to the inner type from it. With the above, and a nifty extension method:
public static class DisposableExtensions
{
public static DisposableWrapper<T> Wrap<T>(this T instance)
{
return new DisposableWrapper<T>(instance);
}
}
Let's imagine that I have a service I am injecting into a type, it could be:
public interface IUserService
{
IUser GetUser();
}
I could potentially do something like:
public HomeController(IUserService service)
{
using (var disposable = service.Wrap())
{
var user = service.GetUser();
// I can even grab it again, implicitly.
IUserService service2 = disposable;
}
}
Now regardless of whether that concrete implementation of IUserService is disposable or not, I can still safely work on the assumption that it doesn't matter.
Another quick console example:
class Program
{
static void Main(string[] args)
{
using (var instance = new ClassA().Wrap())
{
ClassA instanceA = instance;
}
using (var instance = new ClassB().Wrap())
{
ClassB instanceB = instance;
}
Console.ReadKey();
}
}
public class ClassA
{
}
public class ClassB : IDisposable
{
public void Dispose()
{
Console.Write("Disposed");
}
}