I have created my data provider using Repository Pattern.
First, I designed a base repository interface as following:
internal interface IGenericRepository<T, in TResourceIdentifier>
{
Task<IEnumerable<T>> GetManyAsync();
Task<T> GetAsync(TResourceIdentifier id);
Task PutAsync(T model);
Task<T> PostAsync(T model);
Task DeleteAsync(TResourceIdentifier id);
}
Then I implemented it:
public class GenericRepository<T, TResourceIdentifier> : IDisposable, IGenericRepository<T, TResourceIdentifier>
where T : class
{
private bool _disposed;
protected HttpClientHelper<T, TResourceIdentifier> Client;
protected GenericRepository(string addressSuffix)
{
Client = new HttpClientHelper<T, TResourceIdentifier>(Properties.Settings.Url, addressSuffix);
}
public async Task<IEnumerable<T>> GetManyAsync()
{
return await Client.GetManyAsync();
}
// All other CRUD methods and dispose
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if(_disposed || !disposing) return;
if(Client != null)
{
var mc = Client;
Client = null;
mc.Dispose();
}
_disposed = true;
}
}
Then I created custom repository interface for each of my entities. For example:
internal interface IOrderRepository : IGenericRepository<Order, int>
{
Task<IEnumerable<Order>> GetOrderBySomeConditionAsync(string condition );
}
And finally, I implemented the custom repository:
public class OrderRepository : GenericRepository<Order, int>, IOrderRepository
{
public OrderRepository(string addressSuffix) : base(addressSuffix)
{
}
public async Task<IEnumerable<Order>> GetOrderBySomeConditionAsync(string condition)
{
//get all the orders (GetManyAsync()) and then returns the ones meeting the condition
}
}
Note that HttpClientHelperuses HttpClient and needs to be disposed manually.
I have created a MVC web application and have defined the repositories at the class level as such:
IOrderRepository _orderRepository = new OrderRepository();
When I call _orderRepository in my CRUD operations, it does not hit dispose after its use. In order to fix that I have ended up implementing like this:
private async Task<IEnumerable<OrderViewModel>> GetOrders()
{
using(var orderRepository = new OrderRepository())
return await orderRepository.GetManyAsync();
}
This would hit the Dispose but is anti pattern.
What am I missing in my implementation that the instance is not disposed on each call?
You should not be disposing HTTPClient after every request.
[https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests][1]
As the above link says -
Therefore, HttpClient is intended to be instantiated once and reused
throughout the life of an application. Instantiating an HttpClient
class for every request will exhaust the number of sockets available
under heavy loads. That issue will result in SocketException errors.
Possible approaches to solve that problem are based on the creation of
the HttpClient object as singleton or static, as explained in this
Microsoft article on HttpClient usage.
Writing a Dispose method in your generic repository does not mean it will be invoked automatically, whenever you feel like it should. It's intended to be invoked individually, hence why you must either use a using statement (as you have shown), or the Dispose method inside your code.
Alternatively, you can leave that job for the garbage collector.
You should also create a finalizer in your generic repository, if you're convinced on using GC.SuppressFinalize(this);
Read more about that here - When should I use GC.SuppressFinalize()?
As R Jain pointed out, you should also create a static class to hold your HttpClient. You'll have to use HttpResponseMessages for your needs, or HttpContent.
Some more resources to read:
HttpClient single instance with different authentication headers
https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
Related
My application creates IDisposable objects that should be reused, so I create a factory that encapsulates the creation and reuse of those objects, code like this:
public class ServiceClientFactory
{
private static readonly object SyncRoot = new object();
private static readonly Dictionary<string, ServiceClient> Clients = new Dictionary<string, ServiceClient>(StringComparer.OrdinalIgnoreCase);
public static ServiceClient CreateServiceClient(string host)
{
lock(SyncRoot)
{
if (Clients.ContainsKey(host) == false)
{
Clients[host] = new ServiceClient(host);
}
return Clients[host];
}
}
}
public class QueryExecutor
{
private readonly ServiceClient serviceClient;
public QueryExecutor(string host)
{
this.serviceClient = ServiceClientFactory.CreateServiceClient(host);
}
public IDataReader ExecuteQuery(string query)
{
this.serviceClient.Query(query, ...);
}
}
What makes me scratch my head is, ServiceClient is IDisposable, I should dispose them explicitly sometime.
One way is implementing IDisposable in QueryExecutor and dispose ServiceClient when QueryExecutor is disposed, but in this way, (1) when disposing ServiceClient, also needs to notify ServiceClientFactory, (2) cannot reuse ServiceClient instance.
So I think it would be much easier to let ServiceClientFactory manage lifetime of all ServiceClient instances, if I go this way, what is the best practice here to dispose all IDisposable objects created by factory? Hook the AppDomain exit event and manually call Dispose() on every ServiceClient instance?
A couple of things to think about here...
Firstly, what you appear to be describing is some variation of the Flyweight pattern. You have an expensive object, ServiceClient, which you want to reuse, but you want to allow consumer objects to create and destroy at will without breaking the expensive object. Flyweight traditionally does this with reference-counting, which might be a bit old hat.
You'll need to make sure that consumers cannot dispose the ServiceClient directly, so you'll also need a lightweight Facade which intercepts the calls to ServiceClient.Dispose and chooses whether to dispose the real object or not. You should hide the real ServiceClient from consumers.
If all that is feasible, you could rewrite your approach as something like:
// this is the facade that you will work from, instead of ServiceClient
public interface IMyServiceClient : IDisposable
{
void Query(string query);
}
// This is your factory, reworked to provide flyweight instances
// of IMyServiceClient, instead of the real ServiceClient
public class ServiceClientFactory : IDisposable
{
// This is the concrete implementation of IMyServiceClient
// that the factory will create and you can pass around; it
// provides both the reference count and facade implementation
// and is nested inside the factory to indicate that consumers
// should not alter these (and cannot without reflecting on
// non-publics)
private class CachedServiceClient : IMyServiceClient
{
internal ServiceClient _realServiceClient;
internal int _referenceCount;
#region Facade wrapper methods around real ServiceClient ones
void IMyServiceClient.Query(string query)
{
_realServiceClient.Query(query);
}
#endregion
#region IDisposable for the client facade
private bool _isClientDisposed = false;
protected virtual void Dispose(bool disposing)
{
if (!_isClientDisposed)
{
if (Interlocked.Decrement(ref _referenceCount) == 0)
{
// if there are no more references, we really
// dispose the real object
using (_realServiceClient) { /*NOOP*/ }
}
_isClientDisposed = true;
}
}
~CachedServiceClient() { Dispose(false); }
void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
// The object cache; note that it is not static
private readonly ConcurrentDictionary<string, CachedServiceClient> _cache
= new ConcurrentDictionary<string, CachedServiceClient>();
// The method which allows consumers to create the client; note
// that it returns the facade interface, rather than the concrete
// class, so as to hide the implementation details
public IMyServiceClient CreateServiceClient(string host)
{
var cached = _cache.GetOrAdd(
host,
k => new CachedServiceClient()
);
if (Interlocked.Increment(ref cached._referenceCount) == 1)
{
cached._realServiceClient = new ServiceClient(host);
}
return cached;
}
#region IDisposable for the factory (will forcibly clean up all cached items)
private bool _isFactoryDisposed = false;
protected virtual void Dispose(bool disposing)
{
if (!_isFactoryDisposed)
{
Debug.WriteLine($"ServiceClientFactory #{GetHashCode()} disposing cache");
if (disposing)
{
foreach (var element in _cache)
{
element.Value._referenceCount = 0;
using (element.Value._realServiceClient) { }
}
}
_cache.Clear();
_isFactoryDisposed = true;
}
}
~ServiceClientFactory() { Dispose(false); }
void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
// This is just an example `ServiceClient` which uses the default
// implementation of GetHashCode to "prove" that new objects aren't
// created unnecessarily; note it does not implement `IMyServiceClient`
public class ServiceClient : IDisposable
{
private readonly string _host;
public ServiceClient(string host)
{
_host = host;
Debug.WriteLine($"ServiceClient #{GetHashCode()} was created for {_host}");
}
public void Query(string query)
{
Debug.WriteLine($"ServiceClient #{GetHashCode()} asked '{query}' to {_host}");
}
public void Dispose()
{
Debug.WriteLine($"ServiceClient #{GetHashCode()} for {_host} was disposed");
GC.SuppressFinalize(this);
}
}
Secondly, in general, I'd remove the static clauses from the factory and make ServiceClientFactory : IDisposable. You'll see I've done that in my example above.
It may seem like you're just pushing the problem up the chain, but doing so allows you to make this decision on a case-by-case basis, per-something (application, session, request, unit test run -- whatever makes sense) and have the object that represents your something be responsible for the disposal.
If your application would benefit from a single-instance cache then expose a singleton instance as part of an AppContext class (for example) and call AppContext.DefaultServiceClientFactory.Dispose() in your clean-shutdown routine.
The emphasis here is on a clean shutdown. As others have stated, there is no guarantee that your Dispose method will ever actually be called (think power-cycling the machine, mid-run). As such, ideally, ServiceClient.Dispose would not have any tangible side-effects (i.e. beyond freeing resources that would be freed naturally if the process terminates or the machine power-cycles).
If ServiceClient.Dispose does have tangible side-effects, then you have identified a risk here, and you should clearly document how to recover your system from an "unclean" shutdown, in an accompanying user manual.
Thirdly, if both ServiceClient and QueryExecutor objects are intended to be reusable, then let the consumer be responsible for both the creation and disposal.
QueryExecutor only really has to be IDisposable in your sample because it can own a ServiceClient (which is also IDisposable). If QueryExecutor didn't actually create the ServiceClient, it wouldn't be responsible for destroying it.
Instead, have the constructor take a ServiceClient parameter (or, using my rewrite, an IMyServiceClient parameter) instead of a string, so the immediate consumer can be responsible for the lifetime of all objects:
using (var client = AppContext.DefaultServiceClientFactory.CreateServiceClient("localhost"))
{
var query = new QueryExecutor(client);
using (var reader = query.ExecuteReader("SELECT * FROM foo"))
{
//...
}
}
PS: Is there any need for consumers to actually directly access ServiceClient or are there any other objects which need a reference to it? If not, perhaps reduce the chain a little and move this stuff directly to QueryExecutor, i.e. using a QueryExecutorFactory to create flyweight QueryExector objects around cached ServiceClient instances, instead.
Static classes are tricky that way. The constructor for a static class is invoked when an instance member is first invoked. The class is destroyed if and when the application domain is destroyed. If the application terminates abruptly (aborts), there's no guarantee a constructor/finalizer would be called.
Your best bet here is to redesign the class to use a singleton pattern. There are ways to work around this issue, but they require strange, dark magic forces that may cost you your soul.
EDIT: As servy points out, a Singleton won't help here. A destructor is a finalizer, and you won't have any guarantee that it will be called (for a wide variety of reasons). If it were me, I'd simply refactor it to an instantiable class that implements IDisposable, and let the caller deal with calling Dispose. Not ideal, I know, but it's the only way to be sure.
I'm working with a 3rd party object that implements IDisposable. In order to make it unit test "able" I build a wrapper. I understand that object implements IDisposable my wrapper needs to implement IDisposable as well.
public interface IWrapper : IDisposable
{
void Complete();
}
public class Wrapper : IWrapper
{
private readonly ThirdPartyLib lib;
public Wrapper()
{
lib = new ThirdPartyLib();
}
public void Complete()
{
lib.Comlete();
}
public void Dispose()
{
lib.Dispose();
}
}
public class Processor : IProcessor
{
private readonly IWrapper wrapper;
public Processor(IWrapper wrapper)
{
this.wrapper = wrapper;
}
public void Process()
{
// do some work
using (wrapper) {
// do more work
}
}
}
Suppose Processor is injected in some class that is using it and Process() is executed
What happends to wrapper if we call Process() again? - wouldn't ThirdPartyLib() throw an exception since it was created only once (in wrappers constructor) and now it has been disposed
Does it not get disposed as long as there is a reference to it?
Should the wrapper maybe be build in such a way that new() "ing" of ThirdPartyLib be performed not in a constructor but in a seperate method, say Begin() - like so:
public class Wrapper : IWrapper
{
private ThirdPartyLib lib;
public void Begin()
{
lib = new ThirdPartyLib();
}
public void Complete()
{
lib.Comlete();
}
public void Dispose()
{
lib.Dispose();
}
}
Then using it:
using (wrapper.Begin()) {
You're right to be concerned. Calling Process() twice would likely cause an exception. Not calling Process() at all would leave the object undisposed.
There is no simple rule for what you should do instead. There are multiple options, and which can be used depends on other parts of your code that aren't in your question.
If Processor takes a reference to an externally owned Wrapper, then it should not dispose that wrapper at all.
If Processor takes ownership of the Wrapper at construction time, then it should dispose that wrapper at dispose time. This means Processor should implement IDisposable as well.
If Processor can be modified to create a new Wrapper on demand, then that wrapper can be disposed when Process() is done with it.
Or, as you suggested, if Wrapper can be modified to create a ThirdPartyLib on demand, that could work too. But be careful: calling wrapper.Begin(); wrapper.Begin(); would leave one ThirdPartyLib undisposed and unreferenced. You'd need to restructure your API a bit more to prevent this from becoming a problem, and effectively, that would mean turning your Wrapper into a ThirdPartyLibFactory.
I think Processor should not dispose of IWrapper, because it is not the one that instantiated it and it doesn't know if it can be disposed or if it's being injected into other objects. In that case, Processor should not use using with wrapper.
The code to dispose of IWrapper should be in the class that instantiated it in the first place, since that's the one that knows about it's lifecycle.
This question is more of a "how do I do it?", rather than a "what am I doing wrong?". I have a class which is called QueryProcessor that processes queries (think CQRS). That object is injected into my presenters. The QueryProcessor needs to use the kernel to resolve bindings. Injecting the kernel in, either directly or via a factory, is easy. Doing so without causing a memory leak is the trick.
I have verified using a memory profiler that none of my QueryProcessor objects are being garbage collected. The class looks like this:
public sealed class QueryProcessor : IQueryProcessor, IDisposable
{
private readonly IKernelFactory _container;
private bool _disposed;
public QueryProcessor(IKernelFactory container)
{
_container = container;
}
//[DebuggerStepThrough]
public TResult Process<TResult>(IQuery<TResult> query)
{
var handlerType = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult));
dynamic handler = _container.RetrieveKernel().Get(handlerType);
return handler.Handle((dynamic)query);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
// dispose of stuff here
_disposed = true;
}
}
}
public interface IKernelFactory
{
IKernel RetrieveKernel();
}
My composition root is reasonably straightforward. I am using the factory extension of Ninject.
public void OnLoad(IKernel kernel)
{
// Auto-Register all the validators which are stored in the Service assembly.
AssemblyScanner.FindValidatorsInAssembly(_serviceAssembly).ForEach(
result => kernel.Bind(result.InterfaceType, result.ValidatorType)
);
ManualRegistrations(kernel);
kernel.Bind<IKernelFactory>().ToFactory();
AutoRegisterType(kernel, typeof(IQueryHandler<,>));
AutoRegisterType(kernel, typeof(ICommandHandler<>));
}
As mentioned, the injection is working, but it is leaving a memory leak. How am I supposed to get the Ninject kernel resolving stuff in my QueryProcessor without causing the leak?
Thanks
Update - New Problem
I tried to solve this problem by creating a new kernel with a new module, separate from the main kernel of the Composition Root. These sub-kernels would be created and disposed up, with their lifetimes being tied to that of the QueryProcessors. I hooked it up like this in the main module:
kernel.Bind<IQueryProcessor>().ToMethod(ctx => new QueryProcessor(new StandardKernel(new ProcessorModule(_serviceAssembly)))).InTransientScope();
It works fine before the kernel is disposed of for the first time. But after that, I get the following error message:
Error loading Ninject component ICache
No such component has been registered in the kernel's component container.
Suggestions:
1) If you have created a custom subclass for KernelBase, ensure that you have properly
implemented the AddComponents() method.
2) Ensure that you have not removed the component from the container via a call to RemoveAll().
3) Ensure you have not accidentally created more than one kernel.
Damned if I do, damned if I don't ...
Since your application, not the DI container, is creating the instance it is also responsible for disposing the instance. This scenario can be handled by using the Register, Resolve, and Release pattern.
If you inject the kernel, then you have effectively implemented the service locator anti-pattern. This means your application is explicitly dependent on your DI framework.
Rather than injecting the kernel, you should use an abstract factory as mentioned in the post DI Friendly Framework to handle both creating and releasing the handler instances.
public interface IHandlerFactory
{
dynamic Create(Type handlerType);
void Release(dynamic handler);
}
public interface HandlerFactory
{
private readonly Func<Type, dynamic> handlerMethod;
public HandlerFactory(Func<Type, dynamic> handlerMethod)
{
if (handlerMethod == null)
throw new ArgumentNullException("handlerMethod");
this.handlerMethod = handlerMethod;
}
public dynamic Create(Type handlerType)
{
return handlerMethod(handlerType);
}
public void Release(dynamic handler)
{
IDisposable disposable = handler as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
Usage
public sealed class QueryProcessor : IQueryProcessor
{
private readonly IHandlerFactory handlerFactory;
public QueryProcessor(IHandlerFactory handlerFactory)
{
if (handlerFactory == null)
throw new ArgumentNullException("handlerFactory");
this.handlerFactory = handlerFactory;
}
//[DebuggerStepThrough]
public TResult Process<TResult>(IQuery<TResult> query)
{
var handlerType = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult));
dynamic handler = this.handlerFactory.Create(handlerType);
try
{
return handler.Handle((dynamic)query);
}
finally
{
this.handlerFactory.Release(handler);
}
}
}
Note that if you use this approach, you are not requiring every handler to implement IDisposable, nor does your QueryProcessor unnecessarily need to implement IDisposable.
In your composition root, you just need to implement the handler method and register it as a parameter to your factory.
Func<Type, dynamic> handlerMethod = type => (dynamic)kernel.Resolve(type);
kernel.Bind<IHandlerFactory>().To<HandlerFactory>()
.WithConstructorArgument("handlerMethod", handlerMethod);
Of course, if you are processing your handlers asynchronously you have to keep the instance alive until the end of the request rather than disposing it as soon as the handler.Handle() method returns. If that is the case, I suggest you analyze the source code for WebApi to work out what pattern is used to do that when dealing with the System.Web.Http.ApiController.
After googling a while I would like to know which is best pratices for DBContext (EntityFramework or Linq-to-Sql).
In practise I would lie to know which one of the following "patterns" has less cons:
1) Get Code From Here
public class ContextFactory
{
[ThreadStatic]
private static DBDataContext context;
//Get connectionString from web.config
private static readonly string connString = ConfigurationManager.ConnectionStrings["ConnectionString1"].ConnectionString;
public static DBDataContext Context()
{
if (context == null)
context = new DBDataContext(connString);
return context;
}
public static void FlushContext()
{
context = new DBSkillDataContext(connString);
}
}
In this way i use FlushContext each time Controller is initialized.
2) In this way (get code from Here)
public class UnitOfWork : IUnitOfWork, IDisposable
{
DBContext context= null;
IUserRepository userRepo = null;
IAccountRepository accountRepo = null;
public UnitOfWork()
{
context= new DBContext();
userRepo= new UserRepository(context);
accountRepo= new accountRepo(context);
}
public IUserRepository userRepo
{
get
{
return userRepo;
}
}
public IAccountRepository accountRepo
{
get
{
return accountRepo;
}
}
public void Dispose()
{
// If this function is being called the user wants to release the
// resources. lets call the Dispose which will do this for us.
Dispose(true);
// Now since we have done the cleanup already there is nothing left
// for the Finalizer to do. So lets tell the GC not to call it later.
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing == true)
{
//someone want the deterministic release of all resources
//Let us release all the managed resources
context= null;
}
}
~UnitOfWork()
{
// The object went out of scope and finalized is called
// Lets call dispose in to release unmanaged resources
// the managed resources will anyways be released when GC
// runs the next time.
Dispose(false);
}
}
public abstract class AController : Controller
{
private IUnitOfWork IUnitOfWork;
protected IUnitOfWork UnitOfWork_
{
get { return IUnitOfWork; }
}
public AController(IUnitOfWork uow)
{
this.IUnitOfWork = uow;
}
}
public class UserController : AController
{
// use our DbContext unit of work in case the page runs
public UserController()
: this(new UnitOfWork())
{
}
// We will directly call this from the test projects
public UserController(UnitOfWork unitOfWork)
: base (unitOfWork)
{
}
public ActionResult Index()
{
List<User> users= UnitOfWork_.usersRepo.GetUsers();
return View(users);
}
}
So what I'm asking is, which one of the above is best practice to use?
Don't make DbContext static. DbContext is not thread safe and making it static makes it easy to use from multiple threads - especially in we scenarios which may lead to hard to debug/resolve bugs and maybe even data corruption. In additon keeping context alive for extended periods of time is not a good idea - it will track more and more entities and therefore will gradually get slower and slower. It will also prevent GC from collecting objects that are being tracked but are not used.
The other example is much better. DbContext itself is kind of UnitOfWork. I am not sure if I would start with the Reposiory pattern here. I would rather use the DbContext directly and move to using patterns when they emerge from my code and only if there is a benefit from using the pattern (note that patterns require more code that needs to be understood and maintained).
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");
}
}