User: xtoff
Date: 2010/02/19 11:54 AM
Added:
/DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/
TypeUtilMethods.cs
Modified:
/DynamicProxy/trunk/src/Castle.DynamicProxy/
Castle.DynamicProxy-vs2008.csproj
/DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/
ClassProxyInstanceContributor.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/Emitters/
TypeUtil.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Serialization/
ProxyObjectReference.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/
FormatterServicesMethods.cs, TypeMethods.cs
Log:
- fixed (hopefully) DYNPROXY-ISSUE-127 - "Serialization/Deserialization
inconsistence" based on code and idea provided by Ou Liu.
I can't see any way of testing this (not without recycling the process). If
anyone has an idea how to test it, be my guest.
File Changes:
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/
=======================================================
File [modified]: Castle.DynamicProxy-vs2008.csproj
Delta lines: +75 -47
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/ClassProxyInstanceContributor.cs
2010-02-19 17:21:18 UTC (rev 6745)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/ClassProxyInstanceContributor.cs
2010-02-19 18:54:25 UTC (rev 6746)
@@ -1,4 +1,4 @@
-// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+// Copyright 2004-2010 Castle Project - http://www.castleproject.org/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@
using System.Reflection;
using System.Runtime.Serialization;
- using Castle.DynamicProxy.Generators;
using Castle.DynamicProxy.Generators.Emitters;
using Castle.DynamicProxy.Generators.Emitters.CodeBuilders;
using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
@@ -35,7 +34,7 @@
private readonly IList<FieldReference> serializedFields = new
List<FieldReference>();
public ClassProxyInstanceContributor(Type targetType,
IList<MethodInfo> methodsToSkip, Type[] interfaces)
- : base(targetType, interfaces,ProxyTypeConstants.Class)
+ : base(targetType, interfaces, ProxyTypeConstants.Class)
{
#if !SILVERLIGHT
if (targetType.IsSerializable)
@@ -67,60 +66,88 @@
@class.DefineCustomAttribute(attribute);
}
}
+
#if !SILVERLIGHT
- protected override void AddAddValueInvocation(ArgumentReference
serializationInfo, MethodEmitter getObjectData, FieldReference field)
+ protected override void AddAddValueInvocation(ArgumentReference
serializationInfo, MethodEmitter getObjectData,
+ FieldReference
field)
{
serializedFields.Add(field);
base.AddAddValueInvocation(serializationInfo,
getObjectData, field);
}
- protected override void
CustomizeGetObjectData(AbstractCodeBuilder codebuilder, ArgumentReference
serializationInfo, ArgumentReference streamingContext, ClassEmitter emitter)
+ protected override void
CustomizeGetObjectData(AbstractCodeBuilder codebuilder, ArgumentReference
serializationInfo,
+
ArgumentReference streamingContext, ClassEmitter emitter)
{
codebuilder.AddStatement(new ExpressionStatement(
- new
MethodInvocationExpression(serializationInfo,
SerializationInfoMethods.AddValue_Bool,
-
new ConstReference("__delegateToBase").ToExpression(),
-
new ConstReference(delegateToBaseGetObjectData ? 1 : 0).
-
ToExpression())));
+ new
MethodInvocationExpression(
+
serializationInfo,
+
SerializationInfoMethods.AddValue_Bool,
+ new
ConstReference("__delegateToBase").ToExpression(),
+ new
ConstReference(delegateToBaseGetObjectData).
+
ToExpression())));
- if (delegateToBaseGetObjectData)
+ if (delegateToBaseGetObjectData == false)
{
- MethodInfo baseGetObjectData =
targetType.GetMethod("GetObjectData",
-
new[] {typeof (SerializationInfo), typeof (StreamingContext)});
-
- codebuilder.AddStatement(new
ExpressionStatement(
- new
MethodInvocationExpression(baseGetObjectData,
-
serializationInfo.ToExpression(),
-
streamingContext.ToExpression())));
+ EmitCustomGetObjectData(codebuilder,
serializationInfo);
+ return;
}
- else
- {
- LocalReference members_ref =
codebuilder.DeclareLocal(typeof (MemberInfo[]));
- LocalReference data_ref =
codebuilder.DeclareLocal(typeof (object[]));
- codebuilder.AddStatement(new
AssignStatement(members_ref,
-
new MethodInvocationExpression(null,
-
FormatterServicesMethods.
-
GetSerializableMembers,
-
new TypeTokenExpression(targetType))));
+ EmitCallToBaseGetObjectData(codebuilder,
serializationInfo, streamingContext);
+ }
- codebuilder.AddStatement(new
AssignStatement(data_ref,
-
new MethodInvocationExpression(null,
-
FormatterServicesMethods.GetObjectData,
-
SelfReference.Self.ToExpression(),
-
members_ref.ToExpression())));
+ private void EmitCustomGetObjectData(AbstractCodeBuilder
codebuilder, ArgumentReference serializationInfo)
+ {
+ var members =
codebuilder.DeclareLocal(typeof(MemberInfo[]));
+ var data = codebuilder.DeclareLocal(typeof(object[]));
- codebuilder.AddStatement(new
ExpressionStatement(
- new
MethodInvocationExpression(serializationInfo,
SerializationInfoMethods.AddValue_Object,
-
new ConstReference("__data").ToExpression(),
-
data_ref.ToExpression())));
- }
+ var getSerializableMembers = new
MethodInvocationExpression(
+ null,
+ FormatterServicesMethods.GetSerializableMembers,
+ new TypeTokenExpression(targetType));
+ codebuilder.AddStatement(new AssignStatement(members,
getSerializableMembers));
+
+ // Sort to keep order on both serialize and deserialize
side the same, c.f DYNPROXY-ISSUE-127
+ var callSort = new MethodInvocationExpression(
+ null,
+ TypeUtilMethods.Sort,
+ members.ToExpression());
+ codebuilder.AddStatement(new AssignStatement(members,
callSort));
+
+ var getObjectData = new MethodInvocationExpression(
+ null,
+ FormatterServicesMethods.GetObjectData,
+ SelfReference.Self.ToExpression(),
+ members.ToExpression());
+ codebuilder.AddStatement(new AssignStatement(data,
getObjectData));
+
+ var addValue = new MethodInvocationExpression(
+ serializationInfo,
+ SerializationInfoMethods.AddValue_Object,
+ new ConstReference("__data").ToExpression(),
+ data.ToExpression());
+ codebuilder.AddStatement(new
ExpressionStatement(addValue));
}
+ private void EmitCallToBaseGetObjectData(AbstractCodeBuilder
codebuilder, ArgumentReference serializationInfo,
+ ArgumentReference
streamingContext)
+ {
+ MethodInfo baseGetObjectData =
targetType.GetMethod("GetObjectData",
+
new[] { typeof(SerializationInfo), typeof(StreamingContext) });
+
+ codebuilder.AddStatement(new ExpressionStatement(
+ new
MethodInvocationExpression(baseGetObjectData,
+
serializationInfo.ToExpression(),
+
streamingContext.ToExpression())));
+ }
+
private void Constructor(ClassEmitter emitter)
{
#if !SILVERLIGHT
- if (!delegateToBaseGetObjectData) return;
+ if (!delegateToBaseGetObjectData)
+ {
+ return;
+ }
GenerateSerializationConstructor(emitter);
#endif
}
@@ -133,9 +160,9 @@
var ctor = emitter.CreateConstructor(serializationInfo,
streamingContext);
ctor.CodeBuilder.AddStatement(
- new
ConstructorInvocationStatement(serializationConstructor,
-
serializationInfo.ToExpression(),
-
streamingContext.ToExpression()));
+ new
ConstructorInvocationStatement(serializationConstructor,
+
serializationInfo.ToExpression(),
+
streamingContext.ToExpression()));
foreach (var field in serializedFields)
{
@@ -146,7 +173,7 @@
ctor.CodeBuilder.AddStatement(new
AssignStatement(
field,
new
ConvertExpression(field.Reference.FieldType,
-
typeof (object),
+
typeof(object),
getValue)));
}
ctor.CodeBuilder.AddStatement(new ReturnStatement());
@@ -154,14 +181,14 @@
private bool VerifyIfBaseImplementsGetObjectData(Type baseType,
IList<MethodInfo> methodsToSkip)
{
- if (!typeof (ISerializable).IsAssignableFrom(baseType))
+ if (!typeof(ISerializable).IsAssignableFrom(baseType))
{
return false;
}
// If base type implements ISerializable, we have to
make sure
// the GetObjectData is marked as virtual
- var getObjectDataMethod =
baseType.GetInterfaceMap(typeof (ISerializable)).TargetMethods[0];
+ var getObjectDataMethod =
baseType.GetInterfaceMap(typeof(ISerializable)).TargetMethods[0];
Debug.Assert(getObjectDataMethod.Name ==
"GetObjectData");
if (getObjectDataMethod.IsPrivate) //explicit interface
implementation
@@ -181,10 +208,11 @@
methodsToSkip.Add(getObjectDataMethod);
serializationConstructor = baseType.GetConstructor(
- BindingFlags.Instance | BindingFlags.Public |
BindingFlags.NonPublic,
- null,
- new[] { typeof(SerializationInfo),
typeof(StreamingContext) },
- null);
+
BindingFlags.Instance | BindingFlags.Public |
+
BindingFlags.NonPublic,
+
null,
+
new[] { typeof(SerializationInfo), typeof(StreamingContext) },
+
null);
if (serializationConstructor == null)
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/
====================================================================
File [modified]: ClassProxyInstanceContributor.cs
Delta lines: +16 -6
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/Emitters/TypeUtil.cs
2010-02-19 17:21:18 UTC (rev 6745)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/Emitters/TypeUtil.cs
2010-02-19 18:54:25 UTC (rev 6746)
@@ -1,4 +1,4 @@
-// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+// Copyright 2004-2010 Castle Project - http://www.castleproject.org/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -16,11 +16,12 @@
{
using System;
using System.Collections.Generic;
+ using System.Reflection;
public abstract class TypeUtil
{
/// <summary>
- /// Returns list of all unique interfaces implemented given
types, including their base interfaces.
+ /// Returns list of all unique interfaces implemented given
types, including their base interfaces.
/// </summary>
/// <param name="types"></param>
/// <returns></returns>
@@ -36,7 +37,10 @@
IDictionary<Type, object> interfaces = new
Dictionary<Type, object>();
foreach (var type in types)
{
- if(type == null) continue;
+ if (type == null)
+ {
+ continue;
+ }
if (type.IsInterface)
{
@@ -66,7 +70,7 @@
return
parameter.GetGenericTypeDefinition().MakeGenericType(arguments);
}
}
-
+
if (parameter.IsGenericParameter)
{
return type.GetGenericArgument(parameter.Name);
@@ -77,8 +81,8 @@
var elementType = GetClosedParameterType(type,
parameter.GetElementType());
return elementType.MakeArrayType();
}
-
- if(parameter.IsByRef)
+
+ if (parameter.IsByRef)
{
var elementType = GetClosedParameterType(type,
parameter.GetElementType());
return elementType.MakeByRefType();
@@ -87,6 +91,12 @@
return parameter;
}
+ public static MemberInfo[] Sort(MemberInfo[] members)
+ {
+ Array.Sort(members, (l, r) => string.Compare(l.Name,
r.Name));
+ return members;
+ }
+
private static bool
CloseGenericParametersIfAny(AbstractTypeEmitter emitter, Type[] arguments)
{
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/Emitters/
===========================================================================
File [modified]: TypeUtil.cs
Delta lines: +6 -1
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Serialization/ProxyObjectReference.cs
2010-02-19 17:21:18 UTC (rev 6745)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Serialization/ProxyObjectReference.cs
2010-02-19 18:54:25 UTC (rev 6746)
@@ -1,4 +1,4 @@
-// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+// Copyright 2004-2010 Castle Project - http://www.castleproject.org/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
using Castle.DynamicProxy;
using Castle.Core.Interceptor;
using Castle.DynamicProxy.Generators;
+ using Castle.DynamicProxy.Generators.Emitters;
/// <summary>
/// Handles the deserialization of proxies.
@@ -228,6 +229,10 @@
{
var baseMemberData =
GetValue<object[]>("__data");
MemberInfo[] members =
FormatterServices.GetSerializableMembers(baseType);
+
+ // Sort to keep order on both serialize and
deserialize side the same, c.f DYNPROXY-ISSUE-127
+ members = TypeUtil.Sort(members);
+
FormatterServices.PopulateObjectMembers(proxy,
members, baseMemberData);
}
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Serialization/
=====================================================================
File [modified]: ProxyObjectReference.cs
Delta lines: +3 -4
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/FormatterServicesMethods.cs
2010-02-19 17:21:18 UTC (rev 6745)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/FormatterServicesMethods.cs
2010-02-19 18:54:25 UTC (rev 6746)
@@ -1,4 +1,4 @@
-// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+// Copyright 2004-2010 Castle Project - http://www.castleproject.org/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -22,11 +22,10 @@
public static class FormatterServicesMethods
{
public static readonly MethodInfo GetObjectData =
- typeof(FormatterServices).GetMethod("GetObjectData",
- new Type[] { typeof(object), typeof(MemberInfo[]) });
+ typeof(FormatterServices).GetMethod("GetObjectData",
new[] { typeof(object), typeof(MemberInfo[]) });
public static readonly MethodInfo GetSerializableMembers =
-
typeof(FormatterServices).GetMethod("GetSerializableMembers", new Type[] {
typeof(Type) });
+
typeof(FormatterServices).GetMethod("GetSerializableMembers", new[] {
typeof(Type) });
}
}
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/
==============================================================
File [modified]: FormatterServicesMethods.cs
Delta lines: +2 -2
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/TypeMethods.cs
2010-02-19 17:21:18 UTC (rev 6745)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/TypeMethods.cs
2010-02-19 18:54:25 UTC (rev 6746)
@@ -1,4 +1,4 @@
-// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+// Copyright 2004-2010 Castle Project - http://www.castleproject.org/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
public static class TypeMethods
{
public static readonly MethodInfo StaticGetType =
- typeof(Type).GetMethod("GetType", new Type[] {
typeof(string), typeof(bool), typeof(bool) });
+ typeof(Type).GetMethod("GetType", new[] {
typeof(string), typeof(bool), typeof(bool) });
public static readonly MethodInfo GetTypeFromHandle =
File [modified]: TypeMethods.cs
Delta lines: +27 -0
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/TypeUtilMethods.cs
(rev 0)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/TypeUtilMethods.cs
2010-02-19 18:54:25 UTC (rev 6746)
@@ -0,0 +1,27 @@
+// Copyright 2004-2010 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.DynamicProxy.Tokens
+{
+ using System.Reflection;
+
+ using Castle.DynamicProxy.Generators.Emitters;
+
+#if !SILVERLIGHT
+ public static class TypeUtilMethods
+ {
+ public static readonly MethodInfo Sort =
typeof(TypeUtil).GetMethod("Sort",BindingFlags.Public | BindingFlags.Static);
+ }
+#endif
+}
File [added]: TypeUtilMethods.cs
Delta lines: +0 -0
===================================================================
--
You received this message because you are subscribed to the Google Groups
"Castle Project Commits" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/castle-project-commits?hl=en.