4thSpace
4thSpace

Reputation: 44312

How to deserialize when only interface is available?

I have three components:

App calls the Processor library and passes it a class of type:

ClassA : IElement

ClassA is serialized before being passed to Processor. Processor is a base library and does not know about class types such as ClassA. It does know about IElement however. Processor will deserialize the IElement passed to it, which is of type ClassA.

The issue is that an interface cannot be deserialized. But Processor does not know about ClassA and should not. How can I get a reference to the passed in object in this case?

Upvotes: 0

Views: 268

Answers (1)

Paul Keister
Paul Keister

Reputation: 13077

One way to handle this is the create a SerializationBinder implementation that loads classA, then pass a reference to an instance of your binder to Processor.dll so that Processor.dll can use your binder implementation for deserialization. This will allow you to keep the code that references ClassA in the App module (the SerializationBinder implementation will of course have to be defined in the App module).

Here's an example: Given this interface in the Element library

public interface IElement
{
    string DoSomething(string param);
}

you would define your processor like this:

public class ProcessorClass
{
    private SerializationBinder _binder;

    public ProcessorClass(SerializationBinder binder)
    {
        _binder = binder;
    }

    public string CallDoSomething(Stream s)
    {
        var formatter = new BinaryFormatter();

        formatter.Binder = _binder;

       var i = (IElement)formatter.Deserialize(s);

        return i.DoSomething("the processor");
    }
}

In this example, I'm using a very, very simple serialization binder. Note that this must be defined in the App assembly, that's why you don't need a reference to ClassA anywhere besides App.

class Binder : SerializationBinder
{
    //WARNING: demonstration only, DO NOT USE in production code
    public override Type BindToType(string assemblyName, string typeName)
    {
        return Type.GetType("ClassA");
    }
}

Then we bring it all together in the App assembly:

var ms = new MemoryStream();

var formatter = new BinaryFormatter();

var theObject = new ClassA();

formatter.Serialize(ms, theObject);

var processor = new ProcessorClass(new Binder());

ms.Seek(0, SeekOrigin.Begin);

string result = processor.CallDoSomething(ms);

See this This MSDN example for another example of a SerializationBinder.

Upvotes: 1

Related Questions