Cast generic parameter

I get an object back from a method. The object is of type object and I can't change this because of backwards compatibility. If it is of a certain type (Response<T> bellow) then I need to access the property Payload which is of type T so that I can serialize it as part of a another object and send it off. The problem is that since I don't know the type of T I can't cast the object to Response<T> to access Payload even though I don't care about its type.

Here is my object with the generic type:

public class Response
{
   public int Status { get; set; }
   public string Message { get; set; }
}

public class Response<T> : Response
{
   public T Payload { get; set; }
}

Here is what I would like to do:

// Will sometimes be of type Response<T>
object data = LegacyCode();
if (data.GetType().IsGenericType && data.GetType().GetGenericTypeDefinition() == typeof(Response<>)) {
   var payload = ((Response<object>)data).Payload; // Unable to cast object of type...
}

But the only way I could find to do this is by using dynamics.

// Will sometimes be of type Response<T>
object data = LegacyCode();
if (data.GetType().IsGenericType && data.GetType().GetGenericTypeDefinition() == typeof(Response<>)) {
   var payload = ((dynamice)data).Payload;     
}

Don't ask why things are the way they are (I'm wondering that myself). I have to do code gymnastics to keep backwards compatibility in this system. I just want compile time checking on the name of the property.

Here is a fiddle: https://dotnetfiddle.net/dXxHbD

UPDATE:

I need to be able to serialize and deserialize this object. Originally Response had a property Payload of type object. This caused serialization issues when Response<T> was deserialized because the Payload property was of type Newtonsoft.Json.Linq.JObject which could not be cast to T. Here is an example: https://dotnetfiddle.net/uc15HD

The problem was that I was going the wrong direction and the deserialization works if I cast T to object rather than try to cast object to T. When I store the value as its specific type T then the serializer knows what to deserialize the string to. Here is an example using Jon's answer below: https://dotnetfiddle.net/KwudAx

Here is a similar example using Matias' solution of using covariance: https://dotnetfiddle.net/kCjZr4

Jon Skeet
people
quotationmark

To get compile-time checking of the name of the property, you can keep the dynamic typing, but get the runtime "mini-compiler" to do the hard work:

object data = LegacyCode();
object payload = GetPayload(data);
// Use payload

...

private static object GetPayload<T>(Response<T> response)
{
    return response.Payload;
}

public static object GetPayload(object data)
{
    // Fallback method. You could return null here and use
    // that to indicate in the calling code that it wasn't a
    // Response<T>...
}

A much better solution would be to add an non-generic interface or an extra base class though. For example:

public class Response
{
   public int Status { get; set; }
   public string Message { get; set; }
}

public interface IPayloadHolder
{
    public object Payload { get; }
}

public class Response<T> : Response, IPayloadHolder
{
   public T Payload { get; set; }

   // By using explicit interface implementation, this
   // doesn't get in the way for normal usage.
   IPayloadHolder.Payload { get { return Payload; } }
}

Then you can use:

var payloadHolder = data as IPayloadHolder;
if (payloadHolder != null)
{
    var payload = payloadHolder.Payload;
}

people

See more on this question at Stackoverflow