如果我有以下包装类:
public class Wrapper<T>
{
public T Data { get; set; }
public string[] Metadata { get;set;
}
然后另一个类在没有泛型的情况下公开该值:
public class SomeOtherClass
{
public object WrappedData { get;set };
}
,我如何获得原始的未包装数据?
我可以使用以下内容进行测试:
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Wrapper<>))
{
dynamic originalValue = someOtherClass.WrappedData;
}
但我无法调用.Data
上的originalValue
媒体资源,获得RuntimeBinderException
。
更新
更多的背景可能会有所帮助。我正在开发一个WebAPI,我想要实现HATEOAS。所以我的包装器类包含将返回的数据和元数据,我正在编写一个动作过滤器,它将解包数据,将其返回到响应主体中,并将元数据放入响应头。动作过滤器目前实现如下:
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
if (actionExecutedContext.Request.Method == HttpMethod.Get)
{
var objectContent = actionExecutedContext.Response.Content as ObjectContent;
if (objectContent != null)
{
var type = objectContent.ObjectType;
var formatter = actionExecutedContext
.ActionContext
.ControllerContext
.Configuration
.Formatters
.First(f => f.SupportedMediaTypes
.Contains(new MediaTypeHeaderValue(actionExecutedContext
.Response
.Content
.Headers
.ContentType
.MediaType)));
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Wrapper<>))
{
dynamic value = objectContent.Value;
actionExecutedContext.Response.Content = new ObjectContent(value.Data.GetType(), value.Data, formatter);
}
}
}
base.OnActionExecuted(actionExecutedContext);
}
显然,我的所有API端点当前都没有包装他们的数据,所以如果响应没有返回Wrapper<T>
实例,我想退出操作过滤器而不修改响应。如果是,则拉出.Data
的值并用它重写响应主体。
答案 0 :(得分:1)
以下代码有效:
using System;
namespace ConsoleApplication1
{
class Program
{
public class Wrapper<T>
{
public T Data { get; set; }
public string[] Metadata
{
get; set;
}
}
public class SomeOtherClass
{
public object WrappedData { get; set; }
}
static void Main(string[] args)
{
var wrappedData = new Wrapper<int> { Data = 3 };
var someObject = new SomeOtherClass { WrappedData = wrappedData };
dynamic d = someObject.WrappedData;
Console.WriteLine(d.Data);
}
}
}
所以,目前尚不清楚你的问题是什么!
答案 1 :(得分:1)
从发布的代码中不清楚objectContent.ObjectType
是什么,所以我会修改代码以检查实际值:
object value = objectContent.Value;
if (value != null && value.GetType().IsGenericType && value.GetType().GetGenericTypeDefinition() == typeof(Wrapper<>))
{
object data = ((dynamic)value).Data;
actionExecutedContext.Response.Content = new ObjectContent(data.GetType(), data, formatter);
}
但是,如果使用非通用接口备份泛型类,则可以避免反射和动态调用,并使您的生活更轻松。例如
public interface IWrapper
{
object Data { get; }
string[] Metadata { get; }
}
public class Wrapper<T> : IWrapper
{
public T Data { get; set; }
object IWrapper.Data { get { return Data; } }
public string[] Metadata { get; set; }
}
然后你可以做简单的
var wrapper = objectContent.Value as IWrapper;
if (wrapper != null)
{
actionExecutedContext.Response.Content = new ObjectContent(wrapper.Data.GetType(), wrapper.Data, formatter);
}
答案 2 :(得分:0)
如果将类型添加到包装器中会有帮助吗?
public class Wrapper<T>
{
public Type MyType{get;set;}
public T Data { get; set; }
public string[] Metadata { get;set;}
public Wrapper(T data){
MyType = data.GetType();
Data = data;
}
}
答案 3 :(得分:0)
不确切地知道你要做什么:
object obj = new Wrapper<SomeOtherClass> { Data = new SomeOtherClass { WrappedData = "Hello" } };
Type type = obj.GetType();
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Wrapper<>))
{
dynamic data = ((dynamic)obj).Data;
dynamic wrappedData = data.WrappedData;
}
请注意,无法保证WrappedData
属性中包含Data
属性:WrappedData
属于SomeOtherClass
属性,但例如obj
可能是:
object obj = new Wrapper<string> { Data = "Hello" };