Fixing an issue with output parameters that are of type IntPtr
[castle.git] / InversionOfControl / Castle.MicroKernel / Context / CreationContext.cs
blob9ea02e487d43f6fd98c9e24fa406ec6ac6f066c5
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
17 using System;
18 using System.Collections;
19 using System.Reflection;
20 using System.Text;
22 using Castle.MicroKernel.Exceptions;
23 using Castle.Core;
25 /// <summary>
26 /// Used during a component request, passed along to the whole process.
27 /// This allow some data to be passed along the process, which is used
28 /// to detected cycled dependency graphs and now it's also being used
29 /// to provide arguments to components.
30 /// </summary>
31 [Serializable]
32 public sealed class CreationContext : MarshalByRefObject, ISubDependencyResolver
34 /// <summary>Creates a new, empty <see cref="CreationContext" /> instance.</summary>
35 /// <remarks>A new CreationContext should be created every time, as the contexts keeps some state related to dependency resolution.</remarks>
36 public static CreationContext Empty
38 get { return new CreationContext(new DependencyModel[0]); }
41 /// <summary>
42 ///
43 /// </summary>
44 private readonly IHandler handler;
46 /// <summary>
47 /// The list of handlers that are used to resolve
48 /// the component.
49 /// We track that in order to try to avoid attempts to resolve a service
50 /// with itself.
51 /// </summary>
52 private readonly ArrayList handlersChain = new ArrayList();
54 private readonly IDictionary additionalArguments;
56 /// <summary>
57 /// Holds the scoped dependencies being resolved.
58 /// If a dependency appears twice on the same scope, we'd have a cycle.
59 /// </summary>
60 private readonly DependencyModelCollection dependencies;
62 private readonly Type[] genericArguments;
64 public CreationContext(IHandler handler, IDictionary additionalArguments)
66 this.handler = handler;
67 this.additionalArguments = additionalArguments;
68 dependencies = new DependencyModelCollection();
71 public CreationContext(DependencyModel[] dependencies)
73 handler = null;
74 this.dependencies = new DependencyModelCollection(dependencies);
77 public CreationContext(IHandler handler, DependencyModelCollection dependencies, IList handlersChain)
78 : this(handler, (IDictionary)null)
80 this.dependencies = new DependencyModelCollection(dependencies);
81 this.handlersChain.AddRange(handlersChain);
84 public CreationContext(IHandler handler, Type typeToExtractGenericArguments, IDictionary additionalArguments)
85 : this(handler, additionalArguments)
87 genericArguments = ExtractGenericArguments(typeToExtractGenericArguments);
90 public CreationContext(IHandler handler, Type typeToExtractGenericArguments,
91 CreationContext parentContext)
92 : this(handler, parentContext.Dependencies, parentContext.handlersChain)
94 additionalArguments = parentContext.additionalArguments;
95 genericArguments = ExtractGenericArguments(typeToExtractGenericArguments);
98 #region ISubDependencyResolver
100 public object Resolve(CreationContext context, ISubDependencyResolver parentResolver,
101 ComponentModel model, DependencyModel dependency)
103 if (additionalArguments != null)
105 return additionalArguments[dependency.DependencyKey];
108 return null;
111 public bool CanResolve(CreationContext context, ISubDependencyResolver parentResolver,
112 ComponentModel model, DependencyModel dependency)
114 if (dependency.DependencyKey == null) return false;
116 if (additionalArguments != null)
118 return additionalArguments.Contains(dependency.DependencyKey);
121 return false;
124 #endregion
126 public IDictionary AdditionalParameters
128 get { return additionalArguments; }
131 public bool HasAdditionalParameters
133 get { return additionalArguments != null && additionalArguments.Count != 0; }
136 /// <summary>
137 /// Pendent
138 /// </summary>
139 public IHandler Handler
141 get { return handler; }
144 #region Cycle detection related members
146 public DependencyModelCollection Dependencies
148 get { return dependencies; }
151 #endregion
153 public Type[] GenericArguments
155 get { return genericArguments; }
158 private static Type[] ExtractGenericArguments(Type typeToExtractGenericArguments)
160 return typeToExtractGenericArguments.GetGenericArguments();
163 /// <summary>
164 /// Check if we are now in the middle of resolving this handler,
165 /// and as such, we shouldn't try to resolve that.
166 /// </summary>
167 public bool HandlerIsCurrentlyBeingResolved(IHandler handlerToTest)
169 return handlersChain.Contains(handlerToTest);
172 public IDisposable ResolvingHandler(IHandler handlerBeingResolved)
174 handlersChain.Add(handlerBeingResolved);
175 return new RemoveHandlerFromCurrentlyResolving(this, handlerBeingResolved);
178 private class RemoveHandlerFromCurrentlyResolving : IDisposable
180 private readonly CreationContext parent;
181 private readonly IHandler handler;
183 public RemoveHandlerFromCurrentlyResolving(CreationContext parent, IHandler handler)
185 this.parent = parent;
186 this.handler = handler;
189 public void Dispose()
191 parent.handlersChain.Remove(handler);