Removed untyped contructor from ComponentRegistration and add a protected setter.
[castle.git] / Tools / Castle.DynamicProxy2 / Castle.DynamicProxy / Serialization / ProxyObjectReference.cs
blobf8162f8064eed7d5f978deb1a7579c4905ba8248
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.DynamicProxy.Serialization
17 using System;
18 using System.Reflection;
19 using System.Runtime.Serialization;
20 using Castle.DynamicProxy;
21 using Castle.Core.Interceptor;
22 using Castle.DynamicProxy.Generators;
24 /// <summary>
25 /// Handles the deserialization of proxies.
26 /// </summary>
27 [Serializable]
28 public class ProxyObjectReference : IObjectReference, ISerializable, IDeserializationCallback
30 private static ModuleScope _scope = new ModuleScope();
32 private readonly SerializationInfo _info;
33 private readonly StreamingContext _context;
35 private readonly Type _baseType;
36 private readonly Type[] _interfaces;
37 private readonly object _proxy;
38 private readonly ProxyGenerationOptions _proxyGenerationOptions;
40 private bool _isInterfaceProxy;
41 private bool _delegateToBase;
43 /// <summary>
44 /// Resets the <see cref="ModuleScope"/> used for deserialization to a new scope.
45 /// </summary>
46 /// <remarks>This is useful for test cases.</remarks>
47 public static void ResetScope()
49 SetScope (new ModuleScope());
52 /// <summary>
53 /// Resets the <see cref="ModuleScope"/> used for deserialization to a given <paramref name="scope"/>.
54 /// </summary>
55 /// <param name="scope">The scope to be used for deserialization.</param>
56 /// <remarks>By default, the deserialization process uses a different scope than the rest of the application, which can lead to multiple proxies
57 /// being generated for the same type. By explicitly setting the deserialization scope to the application's scope, this can be avoided.</remarks>
58 public static void SetScope (ModuleScope scope)
60 if (scope == null)
61 throw new ArgumentNullException ("scope");
62 _scope = scope;
65 /// <summary>
66 /// Gets the <see cref="DynamicProxy.ModuleScope"/> used for deserialization.
67 /// </summary>
68 /// <value>As <see cref="ProxyObjectReference"/> has no way of automatically determining the scope used by the application (and the application
69 /// might use more than one scope at the same time), <see cref="ProxyObjectReference"/> uses a dedicated scope instance for deserializing proxy
70 /// types. This instance can be reset and set to a specific value via <see cref="ResetScope"/> and <see cref="SetScope"/>.</value>
71 public static ModuleScope ModuleScope
73 get { return _scope; }
76 protected ProxyObjectReference(SerializationInfo info, StreamingContext context)
78 _info = info;
79 _context = context;
81 _baseType = DeserializeTypeFromString("__baseType");
83 String[] _interfaceNames = (String[]) info.GetValue("__interfaces", typeof(String[]));
84 _interfaces = new Type[_interfaceNames.Length];
86 for(int i = 0; i < _interfaceNames.Length; i++)
87 _interfaces[i] = Type.GetType(_interfaceNames[i]);
89 _proxyGenerationOptions = (ProxyGenerationOptions) info.GetValue ("__proxyGenerationOptions", typeof (ProxyGenerationOptions));
90 _proxy = RecreateProxy ();
93 private Type DeserializeTypeFromString (string key)
95 return Type.GetType(_info.GetString(key), true, false);
98 protected virtual object RecreateProxy ()
100 if (_baseType == typeof(object)) // TODO: replace this hack by serializing a flag or something
102 _isInterfaceProxy = true;
103 return RecreateInterfaceProxy();
105 else
107 _isInterfaceProxy = false;
108 return RecreateClassProxy();
112 public object RecreateInterfaceProxy()
114 InterfaceGeneratorType generatorType = (InterfaceGeneratorType) _info.GetInt32("__interface_generator_type");
116 Type theInterface = DeserializeTypeFromString ("__theInterface");
117 Type targetType = DeserializeTypeFromString ("__targetFieldType");
119 InterfaceProxyWithTargetGenerator generator;
120 switch(generatorType)
122 case InterfaceGeneratorType.WithTarget:
123 generator = new InterfaceProxyWithTargetGenerator(_scope, theInterface);
124 break;
125 case InterfaceGeneratorType.WithoutTarget:
126 generator = new InterfaceProxyWithoutTargetGenerator(_scope, theInterface);
127 break;
128 case InterfaceGeneratorType.WithTargetInterface:
129 generator = new InterfaceProxyWithTargetInterfaceGenerator(_scope, theInterface);
130 break;
131 default:
132 throw new InvalidOperationException(
133 string.Format(
134 "Got value {0} for the interface generator type, which is not known for the purpose of serialization.",
135 generatorType));
138 Type proxy_type = generator.GenerateCode(targetType, _interfaces, _proxyGenerationOptions);
139 return FormatterServices.GetSafeUninitializedObject (proxy_type);
142 public object RecreateClassProxy()
144 _delegateToBase = _info.GetBoolean ("__delegateToBase");
146 ClassProxyGenerator cpGen = new ClassProxyGenerator(_scope, _baseType);
148 Type proxy_type = cpGen.GenerateCode(_interfaces, _proxyGenerationOptions);
151 if (_delegateToBase)
153 return Activator.CreateInstance(proxy_type, new object[] {_info, _context});
155 else
157 return FormatterServices.GetSafeUninitializedObject(proxy_type);
161 protected void InvokeCallback(object target)
163 if (target is IDeserializationCallback)
165 (target as IDeserializationCallback).OnDeserialization(this);
169 public object GetRealObject(StreamingContext context)
171 return _proxy;
174 public void GetObjectData(SerializationInfo info, StreamingContext context)
176 // There is no need to implement this method as
177 // this class would never be serialized.
180 public void OnDeserialization (object sender)
182 IInterceptor[] _interceptors = (IInterceptor[]) _info.GetValue ("__interceptors", typeof (IInterceptor[]));
183 SetInterceptors (_interceptors);
185 if (_isInterfaceProxy)
187 object target = _info.GetValue ("__target", typeof (object));
188 SetTarget (target);
190 else if (!_delegateToBase)
192 object[] baseMemberData = (object[]) _info.GetValue ("__data", typeof (object[]));
193 MemberInfo[] members = FormatterServices.GetSerializableMembers (_baseType);
194 FormatterServices.PopulateObjectMembers (_proxy, members, baseMemberData);
197 InvokeCallback (_proxy);
200 private void SetTarget (object target)
202 FieldInfo targetField = _proxy.GetType ().GetField ("__target");
203 if (targetField == null)
205 throw new SerializationException (
206 "The SerializationInfo specifies an invalid interface proxy type, which has no __target field.");
209 targetField.SetValue (_proxy, target);
212 private void SetInterceptors (IInterceptor[] interceptors)
214 FieldInfo interceptorField = _proxy.GetType ().GetField ("__interceptors");
215 if (interceptorField == null)
217 throw new SerializationException (
218 "The SerializationInfo specifies an invalid proxy type, which has no __interceptors field.");
221 interceptorField.SetValue (_proxy, interceptors);