0

I have a generic C# interface as follows:

public interface ISerialiser<TV>
{
    void Write( BinaryWriter output, TV value );

    TV Read( BinaryReader input );

    Type GetValueType();
}

of which I have several implementations, this being one of them:

public class BooleanSerialiser : ISerialiser<bool>
{
    public void Write( BinaryWriter output, bool value )
    {
        output.Write( value );
    }

    public bool Read( BinaryReader input )
    {
        return input.ReadBoolean();
    }

    public Type GetValueType()
    {
        return typeof(bool);
    }
}

This and the other implementations need to be added to a linked list - something like this:

private readonly LinkedHashMap<Type,ISerialiser<?>> theSerialisers = 
                 new LinkedHashMap<Type, ISerialiser<?>>();

As you can see, I'm using the Java-style wildcard to signify that there are different types of serialiser to add - I realise this won't possibly compile in C# :)

My question is: how do I 'change things around' so that I'm able to populate the HashMap with whatever type of serialiser I wish, and call the interface methods in the same (or similar) way when I eventually pull the objects out of the HashMap?

David
  • 15,894
  • 22
  • 55
  • 66
  • How are you planning to "call the interface methods" (in particular `Read` and `Write`; no such problem with `GetValueType`) if you do not know what `TV` actually is (because it can be either of several things you have added to the list)? What type would you expect `TV` in those method signatures to be treated as? – O. R. Mapper Dec 06 '13 at 08:38
  • @Knaģis: Not necessarily; in that other question, the particular difficulty (that still hasn't been ruled out for this question) of actually calling one of the generically-typed methods was explicitly not required (only the parameterless `doSomething()` method is called there). – O. R. Mapper Dec 06 '13 at 08:48
  • @O. R. Mapper: My bad - I didn't mean 'call the interface methods', I meant 'call the methods of the derived classes'. – johnnyboyc Dec 06 '13 at 08:56
  • @johnnyboyc: That doesn't change or answer my question. – O. R. Mapper Dec 06 '13 at 08:58

1 Answers1

0

You need to create a base interface ISerializer and create a LinkedHashMap<Type,ISerializer> instead.

Your class would look like this:

public interface ISerializer
{
    void Write(BinaryWriter output, object value);
}
public interface ISerializer<TValue> : ISerializer
{
    void Write(BinaryWriter output, TValue value);
}
public class BooleanSerializer : ISerializer<bool>
{
    public void Write( BinaryWriter output, bool value )
    {
        output.Write( value );
    }

    // explicit interface implementation so that it does not show up in IntelliSense 
    // when you use the class itself (instead of ISerializer).
    ISerializer.Write(BinaryWriter output, object value)
    {
        if (!(value is bool))
             throw new ArgumentOutOfRangeException();
        this.Write(output, (bool)value);
    }
}

You could also benefit from an extension method like this

public static GetSerializer<TValue>(this LinkedHashMap<Type, ISerializer> collection)
{
    return (ISerializer<TValue>)collection[typeof(TValue)];
}
Knaģis
  • 20,827
  • 7
  • 66
  • 80
  • That doesn't seem to quite work - ReSharper seems to still be wanting me to implement the ISerialiser method in the 'regular' way. – johnnyboyc Dec 06 '13 at 09:00