1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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
18 using System
.Collections
;
19 using System
.Reflection
;
22 using Castle
.MicroKernel
.Exceptions
;
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.
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]); }
44 private readonly IHandler handler
;
47 /// The list of handlers that are used to resolve
49 /// We track that in order to try to avoid attempts to resolve a service
52 private readonly ArrayList handlersChain
= new ArrayList();
54 private readonly IDictionary additionalArguments
;
57 /// Holds the scoped dependencies being resolved.
58 /// If a dependency appears twice on the same scope, we'd have a cycle.
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
)
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
];
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
);
126 public IDictionary AdditionalParameters
128 get { return additionalArguments; }
131 public bool HasAdditionalParameters
133 get { return additionalArguments != null && additionalArguments.Count != 0; }
139 public IHandler Handler
141 get { return handler; }
144 #region Cycle detection related members
146 public DependencyModelCollection Dependencies
148 get { return dependencies; }
153 public Type
[] GenericArguments
155 get { return genericArguments; }
158 private static Type
[] ExtractGenericArguments(Type typeToExtractGenericArguments
)
160 return typeToExtractGenericArguments
.GetGenericArguments();
164 /// Check if we are now in the middle of resolving this handler,
165 /// and as such, we shouldn't try to resolve that.
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
);