1 // Copyright 2004-2007 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.
16 using Castle
.DynamicProxy
.Generators
;
18 namespace Castle
.DynamicProxy
.Serialization
21 using System
.Collections
;
22 using System
.Reflection
;
23 using System
.Runtime
.Serialization
;
24 using Castle
.Core
.Interceptor
;
27 /// Handles the deserialization of proxies.
28 /// See here for more details:
29 /// http://groups.google.com/group/castle-project-devel/msg/fb5ef9656d050ba5
32 public class ProxyObjectReference
: IObjectReference
, ISerializable
, IDeserializationCallback
34 private static ModuleScope _scope
= new ModuleScope();
36 private Type _baseType
;
37 private Type
[] _interfaces
;
38 private IInterceptor
[] _interceptors
;
39 private ProxySerializer
.Indirection _data
;
40 private object _proxy
;
43 /// Usefull for test cases
45 public static void ResetScope()
47 _scope
= new ModuleScope();
50 protected ProxyObjectReference(SerializationInfo info
, StreamingContext context
)
52 _interceptors
= (IInterceptor
[])info
.GetValue("__interceptors", typeof (IInterceptor
[]));
53 _baseType
= (Type
)info
.GetValue("__baseType", typeof(Type
));
55 String
[] _interfaceNames
= (String
[])info
.GetValue("__interfaces", typeof(String
[]));
57 _interfaces
= new Type
[_interfaceNames
.Length
];
59 for (int i
= 0; i
< _interfaceNames
.Length
; i
++)
61 _interfaces
[i
] = Type
.GetType(_interfaceNames
[i
]);
64 _proxy
= RecreateProxy(info
, context
);
67 protected virtual object RecreateProxy(SerializationInfo info
, StreamingContext context
)
69 if (_baseType
== typeof(object))
71 return RecreateInterfaceProxy(info
, context
);
75 return RecreateClassProxy(info
, context
);
79 public object RecreateInterfaceProxy(SerializationInfo info
, StreamingContext context
)
83 object target
= info
.GetValue("__target", typeof(object));
84 InterfaceGeneratorType generatorType
= (InterfaceGeneratorType
)info
.GetInt32("__interface_generator_type");
85 string interfaceName
= info
.GetString("__theInterface");
86 Type theInterface
= Type
.GetType(interfaceName
, true, false);
87 InterfaceProxyWithTargetGenerator generator
;
88 switch (generatorType
)
90 case InterfaceGeneratorType
.WithTarget
:
91 generator
= new InterfaceProxyWithTargetGenerator(_scope
,theInterface
);
93 case InterfaceGeneratorType
.WithoutTarget
:
94 generator
= new InterfaceProxyGeneratorWithoutTarget(_scope
, theInterface
);
96 case InterfaceGeneratorType
.WithTargetInterface
:
97 generator
= new InterfaceProxyWithTargetInterfaceGenerator(_scope
, theInterface
);
100 throw new InvalidOperationException(string.Format("Got value {0} for the interface generator type, which is not known for the purpose of serialization.", generatorType
));
103 Type proxy_type
= generator
.GenerateCode(target
.GetType(), _interfaces
, ProxyGenerationOptions
.Default
);
105 proxy
= Activator
.CreateInstance(proxy_type
, new object[] { _interceptors, target }
);
110 public object RecreateClassProxy(SerializationInfo info
, StreamingContext context
)
112 bool delegateBaseSer
= info
.GetBoolean("__delegateToBase");
116 ClassProxyGenerator cpGen
= new ClassProxyGenerator(_scope
, _baseType
);
118 Type proxy_type
= cpGen
.GenerateCode(_interfaces
, ProxyGenerationOptions
.Default
);
123 proxy
= Activator
.CreateInstance(proxy_type
, new object[] { info, context }
);
127 proxy
= FormatterServices
.GetSafeUninitializedObject(proxy_type
);
128 _data
= (ProxySerializer
.Indirection
) info
.GetValue("__data", typeof (ProxySerializer
.Indirection
));
130 SetInterceptor(proxy
, proxy_type
);
136 private void SetInterceptor (object proxy
, Type proxy_type
)
138 FieldInfo interceptorField
= proxy_type
.GetField("__interceptors");
140 if (interceptorField
== null)
142 throw new SerializationException(
143 "The SerializationInfo specifies an invalid proxy type, which has no __interceptors field.");
146 interceptorField
.SetValue (proxy
, _interceptors
);
149 protected void InvokeCallback(object target
)
151 if (target
is IDeserializationCallback
)
153 (target
as IDeserializationCallback
).OnDeserialization(this);
157 public object GetRealObject(StreamingContext context
)
162 public void GetObjectData(SerializationInfo info
, StreamingContext context
)
164 // There is no need to implement this method as
165 // this class would never be serialized.
168 // Class proxies must be populated in this method, since only at this point all members held by _data.IndirectedObject
169 // have been fixed up.
170 public void OnDeserialization (object sender
)
174 object[] objectData
= (object[]) _data
.IndirectedObject
;
176 MemberInfo
[] members
= FormatterServices
.GetSerializableMembers (_baseType
);
177 FormatterServices
.PopulateObjectMembers (_proxy
, members
, objectData
);
180 InvokeCallback (_proxy
);