我从方法中获取了一个对象。该对象属于object类型,由于向后兼容性,我无法对其进行更改。如果它是某种类型(Response<T>
下方),那么我需要访问类型为Payload
的属性T
,以便我可以将其序列化为另一个对象的一部分并发送它关了。问题在于,由于我不知道T
的类型,因此即使我不知道,我也无法将对象投放到Response<T>
以访问Payload
关心它的类型。
这是我的通用类型的对象:
public class Response
{
public int Status { get; set; }
public string Message { get; set; }
}
public class Response<T> : Response
{
public T Payload { get; set; }
}
以下是我想做的事情:
// 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...
}
但我能找到的唯一方法是使用动力学。
// Will sometimes be of type Response<T>
object data = LegacyCode();
if (data.GetType().IsGenericType && data.GetType().GetGenericTypeDefinition() == typeof(Response<>)) {
var payload = ((dynamice)data).Payload;
}
不要问为什么事情就像他们一样(我自己也在想)。我必须做代码体操以保持在这个系统中的向后兼容性。 我只想要编译时检查属性的名称。
这是一个小提琴:https://dotnetfiddle.net/dXxHbD
更新
我需要能够序列化和反序列化这个对象。最初Response
的属性Payload
类型为object
。这导致序列化问题在Response<T>
被反序列化时,因为Payload
属性类型为Newtonsoft.Json.Linq.JObject
,无法转换为T
。以下是一个示例:https://dotnetfiddle.net/uc15HD
问题在于,如果我将T
转换为object
而不是尝试将object
转换为T
,我的方向错误并且反序列化有效。当我将值存储为其特定类型T
时,序列化程序知道要将字符串反序列化的内容。
以下是Jon的回答:https://dotnetfiddle.net/KwudAx
以下是使用Matias&#39;的类似示例。使用协方差的解决方案:https://dotnetfiddle.net/kCjZr4
答案 0 :(得分:5)
要获得属性名称的编译时检查,您可以保持动态类型,但获取运行时&#34;迷你编译器&#34;努力工作:
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>...
}
更好的解决方案是添加非泛型接口或额外的基类。例如:
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; } }
}
然后你可以使用:
var payloadHolder = data as IPayloadHolder;
if (payloadHolder != null)
{
var payload = payloadHolder.Payload;
}
答案 1 :(得分:5)
我相信您需要使用covariance。
设计界面IResponse<out T>
:
public interface IResponse<out T>
{
public T Payload { get; }
}
并在Response<T>
上实施。现在您可以将其投射到IResponse<object>
:
Response<string> x = new Response<string>();
IResponse<object> y = x; // implicit cast