Added the ability to change the invocation target in the DefaultProxyFactory.
[castle.git] / InversionOfControl / Castle.Windsor / Proxy / DefaultProxyFactory.cs
blobc52060ce777af067169a87f71faa3acb8d69ddd1
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.Windsor.Proxy
17 using System;
18 using System.Reflection;
19 using System.Runtime.Serialization;
20 using Castle.Core;
21 using Castle.Core.Interceptor;
22 using Castle.DynamicProxy;
23 using Castle.MicroKernel;
24 using Castle.MicroKernel.Proxy;
26 /// <summary>
27 /// This implementation of <see cref="IProxyFactory"/> relies
28 /// on DynamicProxy to expose proxy capabilies.
29 /// </summary>
30 /// <remarks>
31 /// Note that only virtual methods can be intercepted in a
32 /// concrete class. However, if the component
33 /// was registered with a service interface, we proxy
34 /// the interface and the methods don't need to be virtual,
35 /// </remarks>
36 [Serializable]
37 public class DefaultProxyFactory : AbstractProxyFactory, IDeserializationCallback
39 [NonSerialized]
40 protected ProxyGenerator generator;
42 /// <summary>
43 /// Constructs a DefaultProxyFactory
44 /// </summary>
45 public DefaultProxyFactory()
47 Init();
50 /// <summary>
51 /// Creates the proxy for the supplied component.
52 /// </summary>
53 /// <param name="kernel">The kernel.</param>
54 /// <param name="target">The target.</param>
55 /// <param name="model">The model.</param>
56 /// <param name="constructorArguments">The constructor arguments.</param>
57 /// <returns>The component proxy.</returns>
58 public override object Create(IKernel kernel, object target, ComponentModel model,
59 params object[] constructorArguments)
61 object proxy;
63 IInterceptor[] interceptors = ObtainInterceptors(kernel, model);
65 ProxyOptions proxyOptions = ProxyUtil.ObtainProxyOptions(model, true);
66 ProxyGenerationOptions proxyGenOptions = CreateProxyGenerationOptionsFrom(proxyOptions);
68 CustomizeOptions(proxyGenOptions, kernel, model, constructorArguments);
70 Type[] interfaces = proxyOptions.AdditionalInterfaces;
72 if (model.Service.IsInterface)
74 if (proxyOptions.OmitTarget)
76 proxy = generator.CreateInterfaceProxyWithoutTarget(model.Service, interfaces,
77 proxyGenOptions, interceptors);
79 else if (proxyOptions.AllowChangeTarget)
81 proxy = generator.CreateInterfaceProxyWithTargetInterface(model.Service, target,
82 proxyGenOptions, interceptors);
84 else
86 if (!proxyOptions.UseSingleInterfaceProxy)
88 interfaces = CollectInterfaces(interfaces, model);
91 proxy = generator.CreateInterfaceProxyWithTarget(model.Service, interfaces,
92 target, proxyGenOptions, interceptors);
95 else
97 proxy = generator.CreateClassProxy(model.Implementation, interfaces, proxyGenOptions,
98 constructorArguments, interceptors);
101 CustomizeProxy(proxy, proxyGenOptions, kernel, model);
103 return proxy;
106 protected static ProxyGenerationOptions CreateProxyGenerationOptionsFrom(ProxyOptions proxyOptions)
108 ProxyGenerationOptions proxyGenOptions = new ProxyGenerationOptions();
110 if (proxyOptions.Hook != null)
112 proxyGenOptions.Hook = new ProxyGenerationHookAdapter(proxyOptions.Hook);
115 if (proxyOptions.UseMarshalByRefAsBaseClass)
117 proxyGenOptions.BaseTypeForInterfaceProxy = typeof(MarshalByRefObject);
120 return proxyGenOptions;
123 protected virtual void CustomizeProxy(object proxy, ProxyGenerationOptions options,
124 IKernel kernel, ComponentModel model)
128 protected virtual void CustomizeOptions(ProxyGenerationOptions options, IKernel kernel,
129 ComponentModel model, object[] arguments)
133 /// <summary>
134 /// Determines if the component requiries a target instance for proxying.
135 /// </summary>
136 /// <param name="kernel">The kernel.</param>
137 /// <param name="model">The model.</param>
138 /// <returns>true if an instance is required.</returns>
139 public override bool RequiresTargetInstance(IKernel kernel, ComponentModel model)
141 ProxyOptions proxyOptions = ProxyUtil.ObtainProxyOptions(model, true);
143 return model.Service.IsInterface && !proxyOptions.OmitTarget;
146 protected Type[] CollectInterfaces(Type[] interfaces, ComponentModel model)
148 Type[] modelInterfaces = model.Implementation.FindInterfaces(
149 new TypeFilter(EmptyTypeFilter), model.Service);
151 if (interfaces == null || interfaces.Length == 0)
153 interfaces = modelInterfaces;
155 else if (modelInterfaces != null && modelInterfaces.Length > 0)
157 Type[] allInterfaces = new Type[interfaces.Length + modelInterfaces.Length];
158 interfaces.CopyTo(allInterfaces, 0);
159 modelInterfaces.CopyTo(allInterfaces, interfaces.Length);
160 interfaces = allInterfaces;
163 return interfaces;
166 private bool EmptyTypeFilter(Type type, object criteria)
168 Type mainInterface = (Type) criteria;
170 return !type.IsAssignableFrom(mainInterface);
173 #region IDeserializationCallback
175 public void OnDeserialization(object sender)
177 Init();
180 #endregion
182 private void Init()
184 generator = new ProxyGenerator();