Fixing an issue with output parameters that are of type IntPtr
[castle.git] / InversionOfControl / Castle.MicroKernel / Lifestyle / PerWebRequestLifestyleManager.cs
blob5dc97d49cb4dad6d0df3034eda46f2135a614188
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.MicroKernel.Lifestyle
17 using System;
18 using System.Collections;
19 using System.Configuration;
20 using System.Web;
22 /// <summary>
23 /// Implements a Lifestyle Manager for Web Apps that
24 /// create at most one object per web request.
25 /// </summary>
26 [Serializable]
27 public class PerWebRequestLifestyleManager : AbstractLifestyleManager
29 private string PerRequestObjectID = "PerRequestLifestyleManager_" + Guid.NewGuid().ToString();
31 #region ILifestyleManager Members
33 public override object Resolve(CreationContext context)
35 HttpContext current = HttpContext.Current;
37 if (current == null)
38 throw new InvalidOperationException(
39 "HttpContext.Current is null. PerWebRequestLifestyle can only be used in ASP.Net");
41 if (current.Items[PerRequestObjectID] == null)
43 if (!PerWebRequestLifestyleModule.Initialized)
45 string message = "Looks like you forgot to register the http module " +
46 typeof(PerWebRequestLifestyleModule).FullName +
47 "\r\nAdd '<add name=\"PerRequestLifestyle\" type=\"Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.MicroKernel\" />' " +
48 "to the <httpModules> section on your web.config";
50 throw new ConfigurationErrorsException(message);
53 object instance = base.Resolve(context);
54 current.Items[PerRequestObjectID] = instance;
55 PerWebRequestLifestyleModule.RegisterForEviction(this, instance);
58 return current.Items[PerRequestObjectID];
61 public override void Release(object instance)
63 // Since this method is called by the kernel when an external
64 // request to release the component is made, it must do nothing
65 // to ensure the component is available during the duration of
66 // the web request. An internal Evict method is provided to
67 // allow the actual releasing of the component at the end of
68 // the web request.
71 internal void Evict(object instance)
73 base.Release(instance);
76 public override void Dispose()
80 #endregion
83 #region PerWebRequestLifestyleModule
85 public class PerWebRequestLifestyleModule : IHttpModule
87 private static bool initialized;
89 private const string PerRequestEvict = "PerRequestLifestyleManager_Evict";
91 public void Init(HttpApplication context)
93 initialized = true;
94 context.EndRequest += new EventHandler(Application_EndRequest);
97 public void Dispose()
101 internal static void RegisterForEviction(PerWebRequestLifestyleManager manager, object instance)
103 HttpContext context = HttpContext.Current;
105 IDictionary candidates = (IDictionary) context.Items[PerRequestEvict];
107 if (candidates == null)
109 candidates = new Hashtable();
110 context.Items[PerRequestEvict] = candidates;
113 candidates.Add(manager, instance);
116 protected void Application_EndRequest(Object sender, EventArgs e)
118 HttpApplication application = (HttpApplication) sender;
119 IDictionary candidates = (IDictionary) application.Context.Items[PerRequestEvict];
121 if (candidates != null)
123 foreach(DictionaryEntry candidate in candidates)
125 PerWebRequestLifestyleManager manager =
126 (PerWebRequestLifestyleManager) candidate.Key;
127 manager.Evict(candidate.Value);
130 application.Context.Items.Remove(PerRequestEvict);
134 internal static bool Initialized
136 get { return initialized; }
140 #endregion