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.

Reply via email to