EntLib CacheManager and IDisposable objects - caching

How do I go about caching objects that implement the IDisposable interface using the CacheManager from the Microsoft Enterprise Library?
When an object expires, Dispose() is never called for that object and I can't override Remove(...) either.

It's not entirely clear to me that it should be the cache's responsibility to call Dispose; just because an item is removed from the cache does not mean that it is not being referenced elsewhere.
Also, if an object implements the IDisposable pattern then the Finalizer should call Dispose (if Dispose has not already been called).
However, Enterprise Library does give you a hook to allow you to perform any actions you deem necessary. The interface is the ICacheItemRefreshAction interface. When an item is removed from the cache the ICacheItemRefreshAction.Refresh method will be invoked on a separate thread.
When an item is added to the cache the ICacheItemRefreshAction can be specified.
An example of its usage:
[Serializable]
public class DisposeRefreshAction : ICacheItemRefreshAction
{
public void Refresh(string key, object expiredValue, CacheItemRemovedReason removalReason)
{
// Item has been removed from cache. Perform desired actions here, based on
// the removal reason (for example, refresh the cache with the item).
if (expiredValue != null && expiredValue is IDisposable)
{
((IDisposable)expiredValue).Dispose();
}
}
}
public class MyClass : IDisposable
{
public void Dispose()
{
Console.WriteLine("Dispose!");
}
}
var cache = EnterpriseLibraryContainer.Current.GetInstance<CacheManager>("Cache Manager");
cache.Add("myKey", new MyClass(), CacheItemPriority.Normal,
new DisposeRefreshAction(), new SlidingTime(TimeSpan.FromSeconds(2)));

Related

LiveData Object keeps being null after getValue() is called

I want to update a member variable of an object inside my Repository on a LiveData- Object. The problem is, that if I call the getValue() Method, I keep getting an NullPointerException, although the value does exist inside my Room- Library.
My question now is, how do I get the value from the LiveData Object without calling the observe() Method? (I am not able to call the observe method inside my repository, cause that method wants me to enter a LifeCycleOwner- reference, which is not present inside my repository).
Is there any way to get the value out of the LiveData- object?
My architecture looks like that:
ViewModel --> Repository --> Dao
You need to initialize LiveData object in ViewModel before observing it in Activity/Fragment like this
ProductViewModel.java
public ProductViewModel(DataRepository repository, int productId) {
mObservableProduct = repository.loadProduct(mProductId);
}
public LiveData<ProductEntity> getObservableProduct() {
return mObservableProduct;
}
Here observableProduct is LiveData for observing product details which is initialized in constructor and fetched using getObservableProduct() method
Then you can observe the LiveData in Activity/Fragment like this
MainActivity.java
productViewModel.getObservableProduct().observe(this, new Observer<ProductEntity>() {
#Override
public void onChanged(#Nullable ProductEntity productEntity) {
mProduct = productEntity;
}
});
As you already setup your code architecture like
Flow of LiveData is
DAO -> Repository -> ViewModel -> Fragment
You don't need to observe LiveData in repository because you cannot update UI from there. Observe it from Activity instead and update UI from there.
As you are saying its giving null on getValue(), make sure you are updating db and fetching db from single instance of DAO as per I worked with DAO it will not notify db update of one DAO instance to 2nd DAO instance with LiveData
Also you can observeForever as suggested by #Martin Ohlin, but it will not be lifecycle aware and may lead to crashes. Check your requirement before observing forever
Refer to this for Full LiveData Flow
Refer to this for DAO issues
Edit 1 - Without using LifecycleOwner
You can use void observeForever (Observer<T> observer) (reference) method to observe LiveData without providing any LifecycleOwner as I provided by using this context in above example.
This is how you can observe LiveData without providing any LifecycleOwner and observe the LiveData in repository itself
private void observeForeverProducts() {
mDatabase.productDao().loadAllProducts().observeForever(new Observer<List<ProductEntity>>() {
#Override
public void onChanged(#Nullable List<ProductEntity> productEntities) {
Log.d(TAG, "onChanged: " + productEntities);
}
});
}
But you need to call removeObserver(Observer) explicitly to stop observing the LiveData which was automatically done in previous case with LifecycleOwner. So as per documentation
You should manually call removeObserver(Observer) to stop observing this LiveData. While LiveData has one of such observers, it will be considered as active.
As this doesn't require LifecycleOwner you can call this in Repository without using this parameter as you mentioned which is missing in your repository
In order for the LiveData object works well you need to use the observe method. That is if you want to use the getValue() method and expecting a non-null response you need to use the observe method. Make sure initialize the LiveData object in your ViewModel as #adityakamble49 said in his answer. For initialize the object, you can pass the reference of your LiveData object which was created in your Repository:
ViewModel.java
private LiveData<Client> clientLiveData;
private ClientRepository clientRepo;
public ViewModel(ClientRepository clientRepo) {
this.clientRepo = clientRepo;
clientLiveData = clientRepo.getData();
}
Then you have to observe your ViewModel from the Activity and call the method that you want to update in your ViewModel (or Repo, but remember that Repo conects with the ViewModel and ViewModel with the UI: https://developer.android.com/jetpack/docs/guide ):
Activity.java
viewModel.getClient().observe(this, new Observer<Client>() {
#Override
public void onChanged(#Nullable Client client) {
viewModel.methodWantedInViewModel(client);
}
});
I hope it helps.
I'm not sure exactly what you are trying to accomplish here, but it is possible to observe without a LifeCycleOwner if you use
observeForever instead of observe.
Livedata is used to observe the data streams. In case you want to call the get a list of your entities stored within the Live Data. Something like this can be helpful.
public class PoliciesTabActivity extends AppCompatActivity {
private PolicyManualViewModel mViewModel;
private List<PolicyManual> policyManualList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leaves_tab_manager);
mViewModel = ViewModelProviders.of(PoliciesTabActivity.this).get(PolicyManualViewModel.class);
//Show loading screen untill live data onChanged is triggered
policyManualList = new ArrayList<>();
mViewModel.getAllPolicies().observe(this, new Observer<List<PolicyManual>>() {
#Override
public void onChanged(#Nullable List<PolicyManual> sections) {
//Here you got the live data as a List of Entities
policyManualList = sections;
if (policyManualList != null && policyManualList.size() > 0) {
Toast.makeText(PoliciesTabActivity.this, "Total Policy Entity Found : " + policyManualList.size(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(PoliciesTabActivity.this, "No Policy Found.", Toast.LENGTH_SHORT).show();
}
}
});
}
}
One more thing - for others with a similar problem - be aware that live data queries will execute only if there is a live observer (i.e. view listening for updates). It won't fill itself just by "laying" there in declarations, like this:
val myLiveData = repository.readSomeLiveData ()
So make sure that you are observing somewhere your LiveData object, either in view or through Transformations.

Are there any problems with using a static property to return DbContext

I've been trying to implement a new MVC3 project with Entity Framework 4.1, which instantiates the dbContext on Application_BeginRequest, and disposes it on Application_EndRequest
protected virtual void Application_BeginRequest()
{
HttpContext.Current.Items["_EntityContext"] = new EntityContext();
}
protected virtual void Application_EndRequest()
{
var entityContext = HttpContext.Current.Items["_EntityContext"] as EntityContext;
if (entityContext != null)
entityContext.Dispose();
}
The EntityContext class is defined as follows:
public class EntityContext : MyEntities, IDisposable
{
**//should this be static?**
public static EntityContext Current
{
get { return HttpContext.Current.Items["_EntityContext"] as EntityContext; }
}
void IDisposable.Dispose()
{
Current.Dispose();
}
My question is, will defining my Current property as static cause any problems in a multi-user scenario?
Your lifespan on DbContext is WAY too long. You should be spinning up a bare minimum of one per request, and even better one per access to the database.
As insta pointed out, you should instance the context when you actually need it. There's no advantage making your context lifespan that long.
As a side-note, there's no need to call explicitly the Dispose method, since the .NET Garbage Collector will do that more efficiently for you.
You could instance the context per class, since you're using MVC, instance the context once per Controller.
public class MyTableObjectController : Controller
{
MyContext context = new MyContext();
public ActionResult Index()
{
var model = context.MyTableObjects;
return View(model);
}
}
I might ask, why are you trying to keep your context available between Begin and End request? Are you trying to avoid instancing it?

Implement Idisposable on mvc3 controller

I have a controller that instantiates a database context for EF. (As I'm sure most that aren't implementing the repository pattern do.)
When I ran code analysis on my project it recommended implementing IDisposable so I wrote the following code.
#region Implementation of IDisposable
public void Dispose()
{
Console.WriteLine("Dispose");
Dispose(true);
GC.SuppressFinalize(this);
}
// The bulk of the clean-up code is implemented in Dispose(bool)
protected override void Dispose(bool disposing)
{
Console.WriteLine("Dispose(disposing)");
if (disposing)
{
// free managed resources
if (_dataService != null)
{
((IDisposable)_dataService).Dispose();
_dataService = null;
}
// free managed resources
if (_db != null)
{
((IDisposable)_db).Dispose();
_db = null;
}
}
base.Dispose(disposing);
}
#endregion
I've also tried doing.
protected new virtual void Dispose(bool disposing)
But my console.writeline statements never execute. What am I doing wrong? Why isn't Dispose() being called on my controller?
you don't do anything wrong. You get the recommentation because you hold some fields in your class (cotnroller) that implements IDisposable. The framework will call the "overload"-version so just move all your code in there.
Details on MSDN
BTW you won't see the console-writeline - use System.Diagnostic.Debug.WriteLine instead
Personally I think the best thing to do in this situation is to split out the database context away from the controller and move it to a service layer. You can them make that class implement IDisposable and pass the reference to the service layer class to the controller to use it
In doing this you will create a controller that is not dependant on the database. The term skinny controllers, fat models applies here. the service layer will act as a model in this instance. You can also unit test the service layer and controller (if you want) in isolation from each other

MVC, EF - DataContext singleton instance Per-Web-Request in Unity

I have a MVC 3 web application, where I am using the Entity Framework for the data access. Furthermore, I have made a simple use of the repository pattern, where e.g. all Product related stuff is handled in the "ProductRepository" and all User related stuff is handled in the "UserRepository".
Thus, I am using the UNITY container, to make a singleton instance of the DataContext, which I inject into each of the repositories. A quick search on Google, and everyone recommends you to NOT use a singleton instance of the DataContext, as it might give you some memory leaks in the future.
So, inspired by this post, making a singleton instance of the DataContext for each web request is the answer (please correct me if I am wrong!)
http://blogs.microsoft.co.il/blogs/gilf/archive/2010/05/18/how-to-manage-objectcontext-per-request-in-asp-net.aspx
However, UNITY does not support the "Per-web-request" lifetime manager. But, it is possible to implement your own custom lifetime manager, which handles this for you. Actually, this is discussed in this post :
Singleton Per Call Context (Web Request) in Unity
The question is, I have now implemented the custom lifetime manager as described in the above post, but I am unsure if this is the way to do it. I am also wondering about where the datacontext instance is disposed in the provided solution? Am I missing out something?
Is there actually a better way of solving my "issue"?
Thanks!
** Added information about my implementation **
The following is snippets from my Global.asax, Controller and Repository. This gives a clear picture of my implementation.
Global.asax
var container = new UnityContainer();
container
.RegisterType<ProductsRepository>(new ContainerControlledLifetimeManager())
.RegisterType<CategoryRepository>(new ContainerControlledLifetimeManager())
.RegisterType<MyEntities>(new PerResolveLifetimeManager(), dbConnectionString)
Controller
private ProductsRepository _productsRepository;
private CategoryRepository _categoryRepository;
public ProductsController(ProductsRepository productsRepository, CategoryRepository categoryRepository)
{
_productsRepository = productsRepository;
_categoryRepository = categoryRepository;
}
public ActionResult Index()
{
ProductCategory category = _categoryRepository.GetProductCategory(categoryId);
.
.
.
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_productsRepository.Dispose();
_categoryRepository.Dispose();
}
Product Repository
public class ProductsRepository : IDisposable
{
private MyEntities _db;
public ProductsRepository(MyEntities db)
{
_db = db;
}
public Product GetProduct(Guid productId)
{
return _db.Product.Where(x => x.ID == productId).FirstOrDefault();
}
public void Dispose()
{
this._db.Dispose();
}
Controller Factory
public class UnityControllerFactory : DefaultControllerFactory
{
IUnityContainer _container;
public UnityControllerFactory(IUnityContainer container)
{
_container = container;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, String.Format("The controller for path '{0}' could not be found" +
"or it does not implement IController.",
requestContext.HttpContext.Request.Path));
}
return _container.Resolve(controllerType) as IController;
}
}
Addition information
Hi, I will post additional links that I come across, concerning the related issue and solution suggestions:
https://github.com/geersch/EntityFrameworkObjectContext
http://dotnetslackers.com/articles/ado_net/Managing-Entity-Framework-ObjectContext-lifespan-and-scope-in-n-layered-ASP-NET-applications.aspx
attaching linq to sql datacontext to httpcontext in business layer
http://weblogs.asp.net/shijuvarghese/archive/2008/10/24/asp-net-mvc-tip-dependency-injection-with-unity-application-block.aspx
http://msdn.microsoft.com/en-us/library/bb738470.aspx
Yes do not share context and use one context per request. You can also check linked questions in that post to see all problems which a shared context caused.
Now about Unity. Idea of PerCallContextLifetimeManager works but I think provided implementation will not work for more than one object. You should use PerHttpRequestLifetimeManager directly:
public class PerHttpRequestLifetime : LifetimeManager
{
// This is very important part and the reason why I believe mentioned
// PerCallContext implementation is wrong.
private readonly Guid _key = Guid.NewGuid();
public override object GetValue()
{
return HttpContext.Current.Items[_key];
}
public override void SetValue(object newValue)
{
HttpContext.Current.Items[_key] = newValue;
}
public override void RemoveValue()
{
var obj = GetValue();
HttpContext.Current.Items.Remove(obj);
}
}
Be aware that Unity will not dispose context for you. Also be aware that default UnityContainer implementation will never call RemoveValue method.
If your implementation resolves all repositories in single Resolve call (for example if your controllers receives instances of repositories in constructor and you are resolving controllers) you don't need this lifetime manager. In such case use build-in (Unity 2.0) PerResolveLifetimeManager.
Edit:
I see pretty big problem in your provided configuration of UnityContainer. You are registering both repositories with ContainerControllerLifetimeManager. This lifetime manager means Singleton instance per container lifetime. It means that both repositories will be instantiated only once and instance will be stored and reused for subsequent calls. Because of that it doesn't matter what lifetime did you assign to MyEntities. It is injected to repositories' constructors which will be called only once. Both repositories will use still that single instance of MyEntities created during their construction = they will use single instance for whole lifetime of your AppDomain. That is the worst scenario you can achieve.
Rewrite your configuration this way:
var container = new UnityContainer();
container
.RegisterType<ProductsRepository>()
.RegisterType<CategoryRepository>()
.RegisterType<MyEntities>(new PerResolveLifetimeManager(), dbConnectionString);
Why this is enough? You are resolving controller which is dependent on repsitories but no repository instance is needed more then once so you can use default TransientLifetimeManager which will create new instance for each call. Because of that repository constructor is called and MyEntities instance must be resolved. But you know that multiple repositories can need this instance so you will set it with PerResolveLifetimeManager => each resolving of controller will produce only one instance of MyEntities.
As of Unity 3, there is already a built-in lifetime manager per http request.
PerRequestLifetimeManager
A LifetimeManager that holds onto the instance given to it during the lifetime of a single HTTP request. This lifetime manager enables you to create instances of registered types that behave like singletons within the scope of an HTTP request. See remarks for important usage information.
Remarks by MSDN
Although the PerRequestLifetimeManager lifetime manager works correctly and can help in working with stateful or thread-unsafe dependencies within the scope of an HTTP request, it is generally not a good idea to use it when it can be avoided, as it can often lead to bad practices or hard to find bugs in the end-user's application code when used incorrectly.
It is recommended that the dependencies you register are stateless and if there is a need to share common state between several objects during the lifetime of an HTTP request, then you can have a stateless service that explicitly stores and retrieves this state using the Items collection of the Current object.
The remarks say that even you are forced to use a single context per service (facade service), you should keep your service calls stateless.
Unity 3 is for .NET 4.5 by the way.
I believe the sample code shown on NerdDinner: DI in MVC using Unity for its HttpContextLifetimeManager should meet your needs.
I don't want to unnecessarily discourage you and by all means experiment but if you go ahead and use singleton instances of DataContext make sure you nail it.
It can appear to work fine on your dev environment but it could be failing to close connections properly. This will be hard to see without the load of a production environment. On a production environment with high load, undisposed connections will cause huge memory leaks and then high CPU trying to allocate new memory.
Have you considered what you are gaining from a connection per request pattern? How much performance there is to gain from opening/closing a connection once over say 3-4 times in a request? Worth the hassle? Also this makes lazy loading fails (read database queries in your view) a lot easier offences to make.
Sorry if this came across discouraging. Go for it if you really see the benefit. I'm just warning you that it could backfire quite seriously if you get it wrong so be warned. Something like entity profiler will be invaluable to getting it right - it tells you number of connections opened and closed - amongst other very useful things.
I saw question and answer few times ago. It is dated. Unity.MVC3 has life time manager as HierarchicalLifetimeManager.
container.RegisterType<OwnDbContext>(
"",
new HierarchicalLifetimeManager(),
new InjectionConstructor(connectionString)
);
and it works nice.
I would propose to solve it like this:
http://forums.asp.net/t/1644386.aspx/1
Best regards
I solved this by using Castle.DynamicProxy. I needed to have certain dependencies be injected "On Demand" meaning they needed to be resolved at time of use, not at time of "Depender" build up.
To do this I configure my container like so:
private void UnityRegister(IUnityContainer container)
{
container.RegisterType<HttpContextBase>(new OnDemandInjectionFactory<HttpContextBase>(c => new HttpContextWrapper(HttpContext.Current)));
container.RegisterType<HttpRequestBase>(new OnDemandInjectionFactory<HttpRequestBase>(c => new HttpRequestWrapper(HttpContext.Current.Request)));
container.RegisterType<HttpSessionStateBase>(new OnDemandInjectionFactory<HttpSessionStateBase>(c => new HttpSessionStateWrapper(HttpContext.Current.Session)));
container.RegisterType<HttpServerUtilityBase>(new OnDemandInjectionFactory<HttpServerUtilityBase>(c => new HttpServerUtilityWrapper(HttpContext.Current.Server)));
}
The idea being that I provide a method to retrieve the instance "on demand." The lambda gets invoked whenever any of the methods of the instance are used. The Dependent object is actually holding a reference to a proxied object, no the object itself.
OnDemandInjectionFactory:
internal class OnDemandInjectionFactory<T> : InjectionFactory
{
public OnDemandInjectionFactory(Func<IUnityContainer, T> proxiedObjectFactory) : base((container, type, name) => FactoryFunction(container, type, name, proxiedObjectFactory))
{
}
private static object FactoryFunction(IUnityContainer container, Type type, string name, Func<IUnityContainer, T> proxiedObjectFactory)
{
var interceptor = new OnDemandInterceptor<T>(container, proxiedObjectFactory);
var proxyGenerator = new ProxyGenerator();
var proxy = proxyGenerator.CreateClassProxy(type, interceptor);
return proxy;
}
}
OnDemandInterceptor:
internal class OnDemandInterceptor<T> : IInterceptor
{
private readonly Func<IUnityContainer, T> _proxiedInstanceFactory;
private readonly IUnityContainer _container;
public OnDemandInterceptor(IUnityContainer container, Func<IUnityContainer, T> proxiedInstanceFactory)
{
_proxiedInstanceFactory = proxiedInstanceFactory;
_container = container;
}
public void Intercept(IInvocation invocation)
{
var proxiedInstance = _proxiedInstanceFactory.Invoke(_container);
var types = invocation.Arguments.Select(arg => arg.GetType()).ToArray();
var method = typeof(T).GetMethod(invocation.Method.Name, types);
invocation.ReturnValue = method.Invoke(proxiedInstance, invocation.Arguments);
}
}
In Unity3, if you want to use
PerRequestLifetimeManager
You need to register UnityPerRequestHttpModule
I do this by using WebActivatorEx, the code is as below:
using System.Linq;
using System.Web.Mvc;
using Microsoft.Practices.Unity.Mvc;
using MyNamespace;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(UnityWebActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(UnityWebActivator), "Shutdown")]
namespace MyNamespace
{
/// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary>
public static class UnityWebActivator
{
/// <summary>Integrates Unity when the application starts.</summary>
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
/// <summary>Disposes the Unity container when the application is shut down.</summary>
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}
PerRequestLifetimeManager and UnityPerRequestHttpModule classes are in Unity.Mvc package which has a dependency on ASP.NET MVC. If you don't want to have that dependency (e.g. you are using Web API) you will have to copy-paste them in to your app.
If you do that, don't forget the register the HttpModule.
Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
Edit:
I'll include the classes here before CodePlex shuts down:
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Web;
using Microsoft.Practices.Unity.Mvc.Properties;
using Microsoft.Practices.Unity.Utility;
namespace Microsoft.Practices.Unity.Mvc
{
/// <summary>
/// Implementation of the <see cref="IHttpModule"/> interface that provides support for using the
/// <see cref="PerRequestLifetimeManager"/> lifetime manager, and enables it to
/// dispose the instances after the HTTP request ends.
/// </summary>
public class UnityPerRequestHttpModule : IHttpModule
{
private static readonly object ModuleKey = new object();
internal static object GetValue(object lifetimeManagerKey)
{
var dict = GetDictionary(HttpContext.Current);
if (dict != null)
{
object obj = null;
if (dict.TryGetValue(lifetimeManagerKey, out obj))
{
return obj;
}
}
return null;
}
internal static void SetValue(object lifetimeManagerKey, object value)
{
var dict = GetDictionary(HttpContext.Current);
if (dict == null)
{
dict = new Dictionary<object, object>();
HttpContext.Current.Items[ModuleKey] = dict;
}
dict[lifetimeManagerKey] = value;
}
/// <summary>
/// Disposes the resources used by this module.
/// </summary>
public void Dispose()
{
}
/// <summary>
/// Initializes a module and prepares it to handle requests.
/// </summary>
/// <param name="context">An <see cref="HttpApplication"/> that provides access to the methods, properties,
/// and events common to all application objects within an ASP.NET application.</param>
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated with Guard class")]
public void Init(HttpApplication context)
{
Guard.ArgumentNotNull(context, "context");
context.EndRequest += OnEndRequest;
}
private void OnEndRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
var dict = GetDictionary(app.Context);
if (dict != null)
{
foreach (var disposable in dict.Values.OfType<IDisposable>())
{
disposable.Dispose();
}
}
}
private static Dictionary<object, object> GetDictionary(HttpContext context)
{
if (context == null)
{
throw new InvalidOperationException(Resources.ErrorHttpContextNotAvailable);
}
var dict = (Dictionary<object, object>)context.Items[ModuleKey];
return dict;
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using Microsoft.Practices.Unity.Mvc;
namespace Microsoft.Practices.Unity
{
/// <summary>
/// A <see cref="LifetimeManager"/> that holds onto the instance given to it during
/// the lifetime of a single HTTP request.
/// This lifetime manager enables you to create instances of registered types that behave like
/// singletons within the scope of an HTTP request.
/// See remarks for important usage information.
/// </summary>
/// <remarks>
/// <para>
/// Although the <see cref="PerRequestLifetimeManager"/> lifetime manager works correctly and can help
/// in working with stateful or thread-unsafe dependencies within the scope of an HTTP request, it is
/// generally not a good idea to use it when it can be avoided, as it can often lead to bad practices or
/// hard to find bugs in the end-user's application code when used incorrectly.
/// It is recommended that the dependencies you register are stateless and if there is a need to share
/// common state between several objects during the lifetime of an HTTP request, then you can
/// have a stateless service that explicitly stores and retrieves this state using the
/// <see cref="System.Web.HttpContext.Items"/> collection of the <see cref="System.Web.HttpContext.Current"/> object.
/// </para>
/// <para>
/// For the instance of the registered type to be disposed automatically when the HTTP request completes,
/// make sure to register the <see cref="UnityPerRequestHttpModule"/> with the web application.
/// To do this, invoke the following in the Unity bootstrapping class (typically UnityMvcActivator.cs):
/// <code>DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));</code>
/// </para>
/// </remarks>
public class PerRequestLifetimeManager : LifetimeManager
{
private readonly object lifetimeKey = new object();
/// <summary>
/// Retrieves a value from the backing store associated with this lifetime policy.
/// </summary>
/// <returns>The desired object, or null if no such object is currently stored.</returns>
public override object GetValue()
{
return UnityPerRequestHttpModule.GetValue(this.lifetimeKey);
}
/// <summary>
/// Stores the given value into the backing store for retrieval later.
/// </summary>
/// <param name="newValue">The object being stored.</param>
public override void SetValue(object newValue)
{
UnityPerRequestHttpModule.SetValue(this.lifetimeKey, newValue);
}
/// <summary>
/// Removes the given object from the backing store.
/// </summary>
public override void RemoveValue()
{
var disposable = this.GetValue() as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
UnityPerRequestHttpModule.SetValue(this.lifetimeKey, null);
}
}
}

Windsor Castle IoC Thread Safety Static Variables

I have a question for the Ioc gurus out there.
I am working with a co-worker to wrap our minds around Castle Windsor IoC. We are having a difference of opinion about static Domain Service objects within asp.Net webforms. We have a static factory called BLServiceFactory in our Infrastructure layer that retrieves the container.
public sealed class BLServiceFactory
{
private static BLServiceFactory _instance = new BLServiceFactory();
IWindsorContainer _container = new WindsorContainer();
public static BLServiceFactory Instance
{
get
{return _instance;}
}
public T Create<T>()
{
return (T)_container[typeof(T)];
}
private BLServiceFactory()
{
_container.AddComponent("DataContext", typeof(DAL.DataContextFactory), typeof(DAL.CPContextFactory));
_container.AddComponent("Repository", typeof(DAL.IRepository<>), typeof(DAL.Repository<>));
_container.AddComponent("UserManager", typeof(BL.IUserManager), typeof(BL.UserManager));
_container.AddComponent("RoleService", typeof(BL.IRoleService), typeof(BL.RoleService));
}
}
We are pulling instances from the factory in our code behinds like this.
public partial class PrintList : System.Web.UI.Page
{
private static readonly ISchoolManager _schoolService = BLServiceFactory.Instance.Create<ISchoolManager>();
Models.TechSchool _tech;
protected void Page_Load(object sender, EventArgs e)
{
_tech = _schoolService.GetSchoolForTechPrep(Profile.UserName);
}
protected void DoOtherStuff...
{
_schoolService.Foo(_tech);
}
}
To me this looks like we will be serving up the same instance to every session. That would indeed be bad! My co-worker thinks that since all of our Domain Services are marked Transient, each page request will get a new instance.
I have also read a bit about memory leaks due to objects marked transient not released for garbage collection. Has this been addressed in the latest release of Castle Windsor, or should I be explicitly releasing objects? Of course as it stands now, all the objects are static and this would be irrelevant.
The BLServiceFactory is a service locator. I recommend using CommonServiceLocator instead of your own if you're going to use a service locator. Component registration does not belong inside the service locator.
Now, in the code you posted, there is no mention of those components being transient, unless you marked them with the [Transient] attribute. If you didn't, those components will be singletons, which is the default lifestyle in Windsor.
Since the variable _schoolService in PrintList is static, the same instance of ISchoolManager will be used for all requests to the PrintList page. If you really want it to be transient, remove the "static" keyword.
About releasing components, see this article.
BTW: AddComponent-style registration is deprecated, use Register() instead.

Resources