I have a set of classes as follows: a Command, which Executes and stores a Result; a Response, which is created as in order to return the Result in a serialized form (plus extra metadata which I've left out). The Response.Result must be of type object, as it is used for a bunch of different commands, each of which can have a Result of any type at all.
The Command is generic, and I'd like it to accept an interface rather than concrete type, but when I do, the serialized response contains the following type hint:
"__type":"ResultOfanyType:#serialization"
rather than the following, which is generated when the command accepts a concrete type:
"__type":"ResultOfMyObjectDhOQ6IBI:#serialization"
I need the type hint to contain the concrete type rather than ResultOfanyType. Why are interfaces being treated differently in this context? Notice that when the Type is a direct property of the serialized Command, then the concrete type is contained in the type hint
I've tried changing the the Result's Response property typed to Result, but that has no effect.
Here is the code. Simply uncomment/comment the lines in Main where the command is created and known types listed for the alternative version.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
namespace serialization
{
class Program
{
static void Main(string[] args)
{
Response response = new Response();
response.ResponseStatus = "ok";
ConcreteCommand command = new ConcreteCommand(); //switch with line below to test inteface
//InterfaceCommand command = new InterfaceCommand();
command.Execute();
response.Results = command.Results;
List<Type> knownTypes = new List<Type>
{
typeof(Result<MyObject>), //switch with Interface lines below to test inteface
typeof(MyObject)
//typeof(Result<IMyObject>),
//typeof(IMyObject)
};
DataContractJsonSerializer serializer = new DataContractJsonSerializer(response.GetType(), knownTypes, int.MaxValue, false, null, true);
Stream stream = new MemoryStream();
serializer.WriteObject(stream, response);
stream.Position = 0;
StreamReader reader = new StreamReader(stream);
string output = reader.ReadToEnd();
Console.WriteLine(output);
}
}
public interface IMyObject
{
string name { get; set; }
}
[DataContract]
[KnownType(typeof(MyObject))]
public class MyObject : IMyObject
{
[DataMember]
public string name { get; set; }
}
[DataContract]
public class Result<T>
{
[DataMember]
public string Status { get; set; }
[DataMember]
public T Item { get; set; }
}
public abstract class BaseCommand<T>
{
protected Result<T> results = new Result<T>();
protected T resultObject;
public object Results
{
get { return this.results; }
}
public T ResultObject
{
get { return this.resultObject; }
}
public abstract void Execute();
}
public class InterfaceCommand : BaseCommand<IMyObject>
{
public override void Execute()
{
IMyObject myobject = new MyObject();
myobject.name = "my object";
Result<IMyObject> result = new Result<IMyObject>();
result.Item = myobject;
result.Status = "ok";
this.results= result;
this.resultObject = myobject;
}
}
public class ConcreteCommand : BaseCommand<MyObject>
{
public override void Execute()
{
MyObject myobject = new MyObject();
myobject.name = "my object";
Result<MyObject> result = new Result<MyObject>();
result.Item = myobject;
result.Status = "ok";
this.results = result;
this.resultObject = myobject;
}
}
[DataContract]
public class Response
{
[DataMember]
public string ResponseStatus { get; set; }
[DataMember]
public object Results { get; set; }
}
}