Dispose of objects references that live longer than the disposing instance - c#

I am currently developing a unit of work and repository pattern on top of NHibernate (As a remark: I didn't made the decision for one or another pattern, therefore please don't discuss the usefulness of the repository pattern in regards to am ORM that already implements one).
I first build per documentation a singleton (using IoC configuration) Sessionmanager that creates Units of Work instances (private methods removed for readability):
public sealed class SessionManager : ISessionManager
{
#region Members
/// <summary>
/// lock to manage thread safe access to the dictionary.
/// </summary>
private readonly ReaderWriterLockSlim _lock;
/// <summary>
/// NHibernate sessionfactory to create sessions.
/// </summary>
private readonly ISessionFactory _factory;
/// <summary>
/// Units of Work that are already in use.
/// </summary>
private readonly Dictionary<string, IUnitOfWork> _units;
/// <summary>
/// Flag indicating if the manager got disposed.
/// </summary>
private bool _disposed;
#endregion
#region Constructors
/// <summary>
/// Creates a new Manager with the given Config.
/// </summary>
/// <param name="config"></param>
public SessionManager(NHibernate.Cfg.Configuration config)
{
_lock = new ReaderWriterLockSlim();
_units = new Dictionary<string, IUnitOfWork>();
_factory = config
.Configure()
.AddAssembly(typeof(SessionManager).Assembly.FullName)
.BuildSessionFactory();
_disposed = false;
}
#endregion
#region Methods
/// <summary>
/// Either creates or returns an existing unit of work.
/// </summary>
/// <param name="identifier">identifier of the uow</param>
/// <param name="access">the data access that is needed for this uow.</param>
/// <returns></returns>
public IUnitOfWork Create(string identifier, DataAccess access)
{
Throw.IfNull(identifier, nameof(identifier));
if (TryGetUnitOfWork(identifier, out var unit))
return unit;
return CreateOrReturn(identifier, access);
}
/// <summary>
/// Disposes the given instance.
/// </summary>
/// <param name="unitOfWork">The unit of work that should get disposed.</param>
public void DisposeUnitOfWork(IUnitOfWork unitOfWork)
{
Throw.IfNull(unitOfWork, nameof(unitOfWork));
try
{
_lock.EnterWriteLock();
if (_units.ContainsValue(unitOfWork))
{
var key = _units.FirstOrDefault(x => x.Value.Equals(unitOfWork)).Key;
if (!string.IsNullOrWhiteSpace(key))
_units.Remove(key);
}
unitOfWork.Dispose();
}
finally
{
_lock.ExitWriteLock();
}
unitOfWork.Dispose();
}
/// <summary>
/// Disposes managed and unmanaged ressources.
/// </summary>
/// <param name="disposing">Flag indicating if the call happened in the public <see cref="Dispose"/> method or the Finalizer.</param>
void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
foreach (var unit in _units)
unit.Value.Dispose();
_factory.Dispose();
_lock.Dispose();
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
_disposed = true;
}
}
/// <summary>
/// Disposes managed and unmanaged ressources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}
The unit of work contains either a ISession or a IStatelessSession to create Transactions or the needed repositories.
public sealed class UnitOfWork : IUnitOfWork
{
#region Members
private bool _disposed;
public string Identifier { get; }
public DataAccess Access { get; }
private readonly ISession _session;
private readonly IStatelessSession _statelessSession;
#endregion
#region Constructors
private UnitOfWork(DataAccess access, string identifier)
{
Access = access;
Identifier = identifier;
_disposed = false;
}
internal UnitOfWork(DataAccess access, string identifier, ISession session)
: this(access, identifier)
{
_session = session;
}
internal UnitOfWork(DataAccess access, string identifier, IStatelessSession session)
: this(access, identifier)
{
_statelessSession = session;
}
#endregion
#region Methods
public void CloseTransaction(IGenericTransaction transaction)
{
transaction.Dispose();
}
public IGenericTransaction OpenTransaction()
{
if (_session != null)
return new GenericTransaction(_session.BeginTransaction());
if (_statelessSession != null)
return new GenericTransaction(_statelessSession.BeginTransaction());
throw new InvalidOperationException("You tried to create a transaction without having a vaild session.");
}
public IGenericTransaction OpenTransaction(IsolationLevel level)
{
if (_session != null)
return new GenericTransaction(_session.BeginTransaction(level), level);
if (_statelessSession != null)
return new GenericTransaction(_statelessSession.BeginTransaction(level), level);
throw new InvalidOperationException("You tried to create a transaction without having a vaild session.");
}
public bool Equals(IUnitOfWork other)
{
if (other == null)
return false;
return Access == other.Access;
}
public IRepository<T> GetRepository<T>() where T : Entity<T>
{
switch (Access)
{
case DataAccess.Statefull:
return new StatefullRepository<T>(_session);
case DataAccess.Stateless:
return new StatelessRepository<T>(_statelessSession);
default:
throw new ArgumentException("Cannot determine which repository is needed.", nameof(Access));
}
}
#region IDisposable Support
void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (_session != null)
_session.Dispose();
if (_statelessSession != null)
_statelessSession.Dispose();
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
_disposed = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~UnitOfWork() {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
#endregion
}
As one can see the Repositories get created using either the ISession or the IStatelessSession. Both of these Interfaces implement the IDisposable interfaces meaning they should get disposed. Therefore my repositories implement IDisposable as well. Here however is the problem. In theory I can create as many repositories as I want from one unit of work e.g. :
public void UpdatePets(List<Cat> felines, List<Dog> carnines, ISessionManager manager)
{
var uow = manager.Create("Pets", DataAccess.Statefull);
using (var t = uow.OpenTransaction())
{
using (var catRepo = uow.GetRepository<Cat>())
{
catRepo.Add(felines);
t.Commit();
}
}
//Some Businesslogic that forbids using one Transaction to mitigate the problem of an already disposed ISession or IStatelessSession.
using(var t = uow.OpenTransaction())
{
using (var dogRepo = uow.GetRepository<Dog>())
{
dogRepo.Add(carnines);
t.Commit();
}
}
}
If that would be the service consuming my unit of work and I would use the "standard" IDisposable Pattern like this:
private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (_session != null)
_session.Dispose();
}
_disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
The second Repository would throw an ObjectDisposedexception because the ISession I reference in the second one is coming from my unit of work and that one was already disposed when my first repository left the using block. So to overcome this Problem I would do the following in my repository:
public void Dispose()
{
_session = null;
GC.SuppressFinalize(this);
}
This however feels wrong because instead of properly disposing the reference to an object that I should dispose I just "close my Eyes and forget about it" which is probably never to good of a solution in programming.
So my question is basically: "Is there a good way to properly dispose objects that might live longer than the object holding the reference?"

You need to establish ownership, and use that to determine which class is responsible for cleaning each "thing" up. It's the owner and only the owner that should call Dispose, no matter how many other classes may have interacted with it.
Ownership needs to be exclusive and (except for wrapper classes) nested1 - the lifetime of the owner needs to be at least as long as the owned object. It's by following these two rules that we can ensure that Dispose is a) called once2 b) when the object is no longer required.
The repositories are the wrong thing to "own" the session. Multiple repositories can be given the same session (so if they're the owners, we've lost the exclusive property), and as your own title alludes to, they have a shorter lifetime than it.
Some general rules of thumb
an object passed as a parameter to an instance method will not normally become owned by the instance.
an object created by an instance and that lives longer than the lifetime of a single method call will be owned by the instance
an object created by an instance method and that doesn't live longer than the lifetime of a single method call will be owned by the method
1For wrappers, the inner object will tend to be created first, possibly configured, then passed to the wrapper object. So the wrapper object's lifetime starts after the inner object.
2Not strictly required. Disposables should tolerate Dispose being called multiple times, but that's more for belt-and-braces defensiveness than a desired pattern.

Related

How to use CancellationToken from one class to another class gracefully?

I have a long running operation in my Winforms project. I am calling a long running synchronization operation from one to another class.
So, In Class1, I am performing a single run of the synchronization operation and calling synchronizer.Synchronize(); which is implemented in Class2.
Any type of MemberShipSynchronization service interupption or Stopped is disposed in Class1 in its Dispose().
From Class2, I am calling the populator.PopulateMembership(); which is implemented in Class3, So, the PopulateMembership() in class3 is long running process.
I want to make this operation Cancellable, means, I want to send the CancellableToken from Class1 to Class3 based on MemberShipSynchronization Service request ( i.e. Stop/Interuppted) and
when the long running operation in Class3 receive the Cancellation request that time I want to Cancel this operation.
So finally, I want to handle this operation gracefully in Class1.
Please suggest a better workaround to achieve this.
=>Class1.
public sealed class MembershipSynchronizationService : IDisposable
{
private readonly object _sync = new object();
/// <summary>
/// Performs a single run of the synchronization service.
/// </summary>
public void RunOnce()
{
lock (_sync)
{
var synchronizer = new MembershipSynchronizer(MembershipManagerUnsecured.SoleInstance.MembershipManager);
synchronizer.Synchronize();
}
}
#region Dispose pattern
/// <summary>
/// Finalizer. Cleans up resources.
/// </summary>
~MembershipSynchronizationService()
{
Dispose(false);
}
/// <summary>
/// Cleans up resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Cleans up resources.
/// </summary>
private void Dispose(bool disposing)
{
if (disposing)
{
lock (_sync)
{
// nothing to do
_ = this;
}
}
}
#endregion
}
=> Class2.
internal sealed class MembershipSynchronizer
{
/// <summary>
/// Performs a single run of the synchronization service.
/// </summary>
public void Synchronize()
{
try
{
TimeSpan elapsed;
var stopwatch = Stopwatch.StartNew();
var populator = _membershipPopulatorFactory.CreatePopulator();
populator.PopulateMembership(); // Time consuming operation.
}
catch (Exception e)
{
LoggingUtility.LogTrace(LoggingCategory.Membership, e);
}
}
=> Class3.
/// <summary>
/// The main implementation of the membership populator.
/// </summary>
public sealed class Populator : IDisposable, IMembershipPopulator
{
public void PopulateMembership()
{
// Code for some time consuming operations.
// ........................................
// ........................................
// ........................................
}
}
}

Problem with an object pooling mechanism, Queue containing the pool can't be static because static variables aren't inherited

I'm setting up an object pooling mechanism in unity, basically how it works is:
You have a base abstract class called "Poolable", with a static queue containing objects in it (In this case GameObjects), there's a class called Projectile which inherits from Poolable as that's what i currently want to be pooled. It further extends to a Bullet class which inherits from Projectile, but the problem is, if i had an Arrow class which inherits from Projectile, it would use the same pool because the pool is static inside Poolable. Does anyone know a way i could tackle this issue?
I thought about making it non-static, but then the objects wouldn't know about the pool, they'd know about their own pool. Same with interfaces but they don't accept variables which aren't properties
The only current fix i see is adding it to each script that i use a pool on, but that then defeats the whole purpose of inheritance as i was trying to make a polymorphic-like structure where you'd have multiple poolables, multiple projectiles, maybe multiple bullets/arrows?
public abstract class Poolable : MonoBehaviour
{
protected static Queue<GameObject> objPool = new Queue<GameObject>(); // doesn't work because every poolable object will use this pool only
[SerializeField] protected GameObject prefab;
public GameObject Get()
{
if(objPool.Count == 0)
{
AddObjects();
}
return objPool.Dequeue();
}
protected void ReturnToPool(GameObject retObj)
{
objPool.Enqueue(retObj);
retObj.SetActive(false);
}
AddObjects()
{
}
}
If I am not mistaken, you need your object pool to be homogeneous. This means your pool contains only one type of object. For example, you don't want arrow and bullet to share the same pool even if they are all projectiles. We don't have c++'s decltype in c#, so if you want your object to have it's non-static member function ReturnToPool, you have to defer type evaluation to run-time (using a type dictionary). Here is the code that would possibly satisfy your need:
using System.Collections.Generic;
using UnityEngine;
using System;
public abstract class Poolable : MonoBehaviour
{
private static Dictionary<Type, Queue<Component>> objPool
= new Dictionary<Type, Queue<Component>>();
/// <summary>
/// Get an object from the pool; If fails, use the alternative method to create one
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="alternativeCreate"></param>
/// <returns></returns>
public static T Get<T>(Func<T> alternativeCreate) where T : Poolable
{
if (objPool.TryGetValue(typeof(T), out var queue) && queue.Count > 0)
{
var ret = queue.Dequeue() as T;
ret.Reactive();
return ret;
}
return alternativeCreate();
}
/// <summary>
/// Return the object to the pool
/// </summary>
public void ReturnToPool()
{
if (this.Reset())
{
var type = this.GetType();
Queue<Component> queue;
if (objPool.TryGetValue(type, out queue))
{
queue.Enqueue(this);
}
else
{
queue = new Queue<Component>();
queue.Enqueue(this);
objPool.Add(type, queue);
}
}
}
/// <summary>
/// Reset the object so it is ready to go into the object pool
/// </summary>
/// <returns>whether the reset is successful.</returns>
protected virtual bool Reset()
{
this.gameObject.SetActive(false);
return true;
}
/// <summary>
/// Reactive the object as it goes out of the object pool
/// </summary>
protected virtual void Reactivate()
{
this.gameObject.SetActive(true);
}
}
You should look into the Singleton Pattern. It's hard to suggest a suitable implementation for what you need because I don't know what you want to do with it, but basically, you can add something like this to your class:
private static Poolable _instance;
private static object _instanceLock = new Object();
public static Poolable Instance
{
get
{
if (_instance == null)
{
lock (_instanceLock)
{
if (_instance == null)
{
this._instance = [Whatever way you instantiate it];
}
}
}
return _instance;
}
}
Afterward, either make the constructor private/protected and make sure you always get your instance with Poolable.Instance.
Hope it helps!

Implement IDisposable in derived class

If I have interface (example from apress book) which implements IDisposable like this
public interface IArchitectRepository : IDisposable
{
IEnumerable<Architect> GetArchitects();
Architect GetAchitectDetails(int id);
void Create(Achitect a);
void Update(Achitect a);
void Delete(int id);
void Save();
}
how would I implement Dispose method in derived class?
In book the it's left as NotImplementedException.
There is no reason why you would implement the Dispose pattern any differently than normal.
See Implementing a Dispose Method
Unlike most interfaces which imply obligations on the part of an implementing class, the only obligation of a class which implements IDisposable is to regard a call to Dispose as adequate notice that an instance is going to be abandoned. The real obligations imparted by IDisposable fall upon instance owners: if a type implements IDisposable, each instance should have one owner who is obligated to ensure that its Dispose method will gets called before it's abandoned; the owner may do this either by calling Dispose itself, or passing ownership to a new owner who would then assume the obligation.
Note that the owner of an IDisposable instance doesn't care what Dispose does provided that the instance may be safely abandoned after it returns. If some particular object can be safely abandoned before Dispose is called, there's no need for the Dispose method to do anything. It should not throw a NotImplementedException or NotSupportedException, since it should be no able to doing everything it needs to do (i.e. nothing).
You should look at MSDN for the complete example: http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
The minimum would be:
public class ArchitectRepository : IArchitectRepository
{
// implement all the IArchitectRepository methods
public void Dispose()
{
// assuming your repository has a connection property
if (this.Connection != null)
this.Connection.Close();
// do the same for all other disposable objects your repository has created.
}
}
Whiting the concrete implementation you can overwrite as follows
public bool IsDisposed { get; set; }
public bool IsLockedForDisposing { get; set; }
/// <summary>
/// Dispose the Loaded Context
/// </summary>
///
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
// Disposing of managed code
context.Dispose();
// GC.Collect(context);
}
this.disposed = true;
}
}
public void Dispose()
{
if (!IsLockedForDisposing)
{
IsDisposed = true;
Dispose(true);
GC.SuppressFinalize(this);
}
}
I have some example code posted here (and included below): How do you properly implement the IDisposable pattern?
Microsoft has slightly more in-depth details here: Implement a Dispose method
#region IDisposable base-class implementation
//TODO remember to make this class inherit from IDisposable -> MyDisposableClass : IDisposable
/// <summary>
/// Gets or sets a value indicating whether this instance is disposed.
/// </summary>
/// <value>
/// <c>true</c> if this instance is disposed; otherwise, <c>false</c>.
/// </value>
/// <remarks>Default initialization for a bool is 'false'</remarks>
private bool IsDisposed { get; set; }
/// <summary>
/// Implementation of Dispose according to .NET Framework Design Guidelines.
/// </summary>
/// <remarks>Do not make this method virtual.
/// A derived class should not be able to override this method.
/// </remarks>
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
// Always use SuppressFinalize() in case a subclass
// of this type implements a finalizer.
GC.SuppressFinalize(this);
}
/// <summary>
/// Overloaded Implementation of Dispose.
/// </summary>
/// <param name="isDisposing"><c>true</c> to release both managed and unmanaged resources;
/// <c>false</c> to release only unmanaged resources.</param>
/// <remarks>
/// <list type="bulleted">Dispose(bool isDisposing) executes in two distinct scenarios.
/// <item>If <paramref name="isDisposing"/> equals true, the method has been called directly
/// or indirectly by a user's code. Managed and unmanaged resources
/// can be disposed.</item>
/// <item>If <paramref name="isDisposing"/> equals <c>false</c>, the method has been called
/// by the runtime from inside the finalizer and you should not reference
/// other objects. Only unmanaged resources can be disposed.</item></list>
/// </remarks>
protected virtual void Dispose(bool isDisposing)
{
// TODO If you need thread safety, use a lock around these
// operations, as well as in your methods that use the resource.
try
{
if (!this.IsDisposed)
{
// Explicitly set root references to null to expressly tell the GarbageCollector
// that the resources have been disposed of and its ok to release the memory
// allocated for them.
if (isDisposing)
{
// Release all managed resources here
// Need to unregister/detach yourself from the events. Always make sure
// the object is not null first before trying to unregister/detach them!
// Failure to unregister can be a BIG source of memory leaks
if (someDisposableObjectWithAnEventHandler != null)
{
someDisposableObjectWithAnEventHandler.SomeEvent -= someDelegate;
someDisposableObjectWithAnEventHandler.Dispose();
someDisposableObjectWithAnEventHandler = null;
}
// If this is a WinForm/UI control, uncomment this code
//if (components != null)
//{
// components.Dispose();
//}
}
// Release all unmanaged resources here
// (example) if (someComObject != null && Marshal.IsComObject(someComObject))
{
Marshal.FinalReleaseComObject(someComObject);
someComObject = null;
}
}
}
finally
{
this.IsDisposed = true;
}
}
//TODO Uncomment this code if this class will contain members which are UNmanaged
///// <summary>Finalizer for MyDisposableClass</summary>
///// <remarks>This finalizer will run only if the Dispose method does not get called.
///// It gives your base class the opportunity to finalize.
///// DO NOT provide finalizers in types derived from this class.
///// All code executed within a Finalizer MUST be thread-safe!</remarks>
// ~MyDisposableClass()
// {
// Dispose( false );
// }
#endregion IDisposable base-class implementation
Here is the code for properly implementing the IDisposable pattern in a derived class:
#region IDisposable derived-class implementation
/// <summary>
/// Gets or sets a value indicating whether this instance is disposed.
/// </summary>
/// <value>
/// <c>true</c> if this instance is disposed; otherwise, <c>false</c>.
/// </value>
/// <remarks>Default initialization for a bool is 'false'</remarks>
private bool IsDisposed { get; set; }
/// <summary>
/// Overloaded Implementation of Dispose.
/// </summary>
/// <param name="isDisposing"><c>true</c> to release both managed and unmanaged resources;
/// <c>false</c> to release only unmanaged resources.</param>
/// <remarks>
/// <list type="bulleted">Dispose(bool isDisposing) executes in two distinct scenarios.
/// <item>If <paramref name="isDisposing"/> equals true, the method has been called directly
/// or indirectly by a user's code. Managed and unmanaged resources
/// can be disposed.</item>
/// <item>If <paramref name="isDisposing"/> equals <c>false</c>, the method has been called
/// by the runtime from inside the finalizer and you should not reference
/// other objects. Only unmanaged resources can be disposed.</item></list>
/// </remarks>
protected override void Dispose(bool isDisposing)
{
// TODO If you need thread safety, use a lock around these
// operations, as well as in your methods that use the resource.
try
{
if (!this.IsDisposed)
{
// Explicitly set root references to null to expressly tell the GarbageCollector
// that the resources have been disposed of and its ok to release the memory
// allocated for them.
if (isDisposing)
{
// Release all managed resources here
// Need to unregister/detach yourself from the events. Always make sure
// the object is not null first before trying to unregister/detach them!
// Failure to unregister can be a BIG source of memory leaks
if (someDisposableObjectWithAnEventHandler != null)
{
someDisposableObjectWithAnEventHandler.SomeEvent -= someDelegate;
someDisposableObjectWithAnEventHandler.Dispose();
someDisposableObjectWithAnEventHandler = null;
}
// If this is a WinForm/UI contrlol, uncomment this code
//if (components != null)
//{
// components.Dispose();
//}
}
// Release all unmanaged resources here
// (example)
if (someComObject != null && Marshal.IsComObject(someComObject))
{
Marshal.FinalReleaseComObject(someComObject);
someComObject = null;
}
}
}
finally
{
this.IsDisposed = true;
// explicitly call the base class Dispose implementation
base.Dispose(isDisposing);
}
}
#endregion IDisposable derived-class implementation

Generic constraint for COM object

I have a generic base class that wraps COM objects and want to constrain it to COM objects.
I tried where TComObject : IUnknown but the compiler does not like it. Is there a way to do this?
I use the code below, please give feedback if you spot something stupid.
public abstract class ComWrapper<TComObject> : IDisposable, IComWrapper<TComObject> where TComObject : class
{
protected ComWrapper(TComObject comObject)
{
ComObject = comObject;
}
protected TComObject ComObject { get; set; }
/// <summary>
/// Use with caution, this accesses the COM object, cleanup might be needed
/// </summary>
/// <returns></returns>
public TComObject GetComObject()
{
return ComObject;
}
public void SetComObject(TComObject comObject)
{
CheckAndReleaseComObject();
ComObject=comObject;
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// free managed resources
}
// free native resources if there are any.
CheckAndReleaseComObject();
}
private void CheckAndReleaseComObject()
{
if (ComObject != null)
{
if (ComObject.GetType().IsCOMObject)
Marshal.ReleaseComObject(ComObject);
ComObject = null;
}
}
}
You cannot set such generic constraint, you could, however, consider using something like Marshal.IsComObject to ensure the object is a COM object. If you specifically want a compile time error, I think you're out of luck.
Also, note that SetComObject can be called multiple times, in which case you don't "clean up" any com object that may already have been set. Also, you can now remove GC.SuppressFinalize, as you removed your finalizer/destructor, which is indeed not needed because the framework will release the com object for you if it would get to a garbage collection.

Creating thread-safe singleton wrapper for DI container

I Created a wrapper for Ninject DI container which I intend to use in WPF application. I would like it to be thread safe in case I need to open new windows in separated threads, but I am confused about using volatile keyword and locking. As much as I'm aware of, locking is pretty much Straightforward to understand but I'm not shore about using volatile keyword. From my googling results I came to understanding that volatile keyword ensures safe read access for specified instance in multithreaded environment but doesn't provide any kind of safety when making changes in memory space occupied by the specified instance. I combined my solution with some examples of thread-safe singleton patterns and came up with this wrapper that would serve me as a service locator:
public class NinjectResolver
{
private static object syncRoot = new object();
private static volatile NinjectResolver instance = null;
private static volatile IKernel kernel = null;
public static NinjectResolver GetInstance()
{
lock (syncRoot)
{
if (instance == null)
instance = new NinjectResolver();
}
return instance;
}
static NinjectResolver()
{
lock (syncRoot)
{
if (kernel == null)
kernel = new StandardKernel();
}
}
public void AddBindings(Dictionary<Type, Type> bindings)
{
lock (syncRoot)
{
foreach (var binding in bindings)
{
Type IType = binding.Key;
Type ImplementationType = binding.Value;
kernel.Bind(IType).To(ImplementationType);
}
}
}
private NinjectResolver()
{
}
/// <summary>
/// Resolves All dependencies for requested instance and returns that instance
/// </summary>
/// <typeparam name="T">Requested Implementation type</typeparam>
/// <returns>Instance of Implementation type</returns>
public T Resolve<T>()
{
return kernel.TryGet<T>();
}
/// <summary>
/// Resolves property injection dependencies in already instantiated Implementation types
/// </summary>
/// <param name="obj">Specified instance of implementation type</param>
public void Inject(object obj)
{
kernel.Inject(obj);
}
}
My question is this: Do I need to use locking in specified places since initialization will take place inside App.xaml.cs (first call of GetInstance() ) and do these static fields need to be declared as volatile or I can omit that part since they are more or less readonly in this construction. I would appreciate if someone could shred some light on this.
To implement a thread-safe singleton pattern you have two options basically:
1.Double-checked locking
public static NinjectResolver GetInstance()
{
if(instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new NinjectResolver();
}
}
return instance;
}
2.Initialize the instance upon declaration
private static volatile NinjectResolver instance = new NinjectResolver();
public static NinjectResolver GetInstance()
{
return instance;
}
Also you can drop the code inside the static block and just use:
private static volatile IKernel kernel = new StandardKernel();

Categories