0

Using BinaryFormatter in C#, I am trying to deserialize objects from a class that includes a delegate property.

After adding a member on the class referred by the delegate the deserialization breaks. See example below.

I would need the deserialization to work even if I completely ignore the problematic delegate property. For example, if the delegate property is always deserialized to null the issue would be solved. I was not able to solve it by marking the property as [NonSerialized] or changing it into a field.

The following would describe the serialized objects that I am trying to deserialize.

public class mySerializedClass
{
    public string thisIsOK1 {get; set;}
    public string thisIsOK2 {get; set;}
    public Func<myModelClass,bool> thisIsTheIssue {get; set;}
}

[Serializable]
public class myModelClass
{
    // The issue happened after adding a new method to this class

    public static bool testMethod(mySerializedClass obj)
    {
        // do stuff
        return true
    }
}

As example of a serialized instance:

new mySerializedClass()
{
    thisIsOK1 = "a";
    thisIsOK2 = "b";
    thisIsTheIssue = (o) => myModelClass.testMethod(o);    
}

A valid solution would be to always serialize/deserialize the "thisIsTheIssue" property to null.

As additional information, the Exception Message is:

Cannot get the member ' get_theNameOfMyDelegate b__19_0'.

And the Exception's StackTrace is:

at System.Reflection.MemberInfoSerializationHolder.GetRealObject(StreamingContext context) at System.Runtime.Serialization.ObjectManager.ResolveObjectReference(ObjectHolder holder) at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream) at ...the place in my code where I deserialize...

donquijote
  • 1,642
  • 5
  • 19
  • 41
  • Please describe "deserialization breaks." The specifics of an exception or error matter. – Scott Hannen Jan 04 '19 at 17:17
  • @ScottHannen, added info on the Exception. Thanks – donquijote Jan 04 '19 at 17:29
  • You mentioned that the exception occurs when you add a method to the second class, and that you tried adding an attribute to prevent serialization. Can you include an example that shows those things? Then perhaps I can create an instance of the class and try to serialize it. – Scott Hannen Jan 04 '19 at 17:37
  • @ScottHannen, added an example instance, hoping it helps, the real case is legacy code, very complex, I hope I and doing a reasonable job describing the issue – donquijote Jan 04 '19 at 18:26
  • 1
    The exception message doesn't match the snippet. But it is in general a pretty bad idea to serialize delegates, especially so when you use a lambda expression. The C# compiler translates them to a method with a wonky name, the odds that this name is stable and it is still "b__19_0" after even a minor code modification are low. When you commit to binary serialization you also commit to never making any changes anymore for as long as the customer's data needs to survive. – Hans Passant Jan 04 '19 at 21:25

1 Answers1

0

I would consider versioning classes, or separating your transport from your working class.

So you might have a mySerializedClass but then have a myWorkingClass

that contains the delegate. On serialization and deserialization, you would load and save myWorkingClass to and from your mySerializedClass. Then from there you can do swifty things like have different versions of mySerializedClass as your application takes on new capabilities.

TJ Bandrowsky
  • 842
  • 8
  • 12
  • The approach you describe would have prevented this issue and could be the way forward in the long term. Given there is serialized data I need to work with I would still need to work on a solution that allowed me to deserialize the existing data even if ignoring the problematic property. To be honest going forward we might prefer to avoid BinaryFormatter altogether. – donquijote Jan 04 '19 at 18:14