如何在不知道typeparam类型的情况下检查对象是否从通用基类继承

时间:2015-08-04 11:24:03

标签: c# generics inheritance reflection type-conversion

我有以下类的构造:

public class Request : BaseRequest, IRequestFromResponse
{
}

定义了一个Request - 通过html格式发布的对象。

Model所居住的Request如下:

public class Response : BaseRequestWrapperResponse<Request>
{
}
在构建BaseWrapper时

public abstract class BaseRequestWrapperResponse<TRequest> where TRequest : IRequestFromResponse
{
    public TRequest Request { get; set; }
}

IRequestFromResponse只是一个空的标记界面。

我尝试在运行时强制转换对象,因此我可以访问Request - BaseRequestWrapperResponse的属性。

到目前为止,我所拥有的只是:

var model = ((ViewContext) context).ViewData.Model;

if (model.GetType().IsSubclassOf(typeof (BaseRequestWrapperResponse<IRequestFromResponse>)))
// if (model.GetType().BaseClass.IsAssignableFrom(typeof (BaseRequestWrapperResponse<IRequestFromResponse>)))
// if (model.GetType().IsSubclassOf(typeof (BaseRequestWrapperResponse<>)))
// if (model.GetType().BaseClass.IsAssignableFrom(typeof (BaseRequestWrapperResponse<>)))
{
    model = ((BaseRequestWrapperResponse<IRequestFromResponse>) model).Request;
}

我无法检查表明model是某种BaseRequestWrapperResponse。演员将成为我的下一个问题。

3 个答案:

答案 0 :(得分:1)

如何添加非通用BaseRequestWrapperResponse类。

public abstract class BaseRequestWrapperResponse 
{
    public IRequestFromResponse Request { get; set; }
}

public abstract class BaseRequestWrapperResponse<TRequest> : BaseRequestWrapperResponse where TRequest : IRequestFromResponse
{
    public new TRequest Request
    {
        get{ return (TRequest)base.Request; }
        set{ base.Request = value; }
    }
}

然后只是:

model = ((BaseRequestWrapperResponse) model).Request;

答案 1 :(得分:0)

这不起作用,因为模型所属的唯一类型是ResponseBaseRequestWrapperResponse<Request>

只要将type参数放入,就必须了解泛型类型是具体类型。因此,Request继承自BaseRequestWrapperResponse<Request>BaseRequestWrapperResponse<Request>是与BaseRequestWrapperResponse<TRequest>没有继承关系的实际类型。它只是一个带有类型参数的副本。

您可以将泛型类型更多地视为 templates ,用于放置泛型类型时创建的实际类型。因此,当您使用BaseRequestWrapperResponse<Request>时,实际上定义了以下类型:< / p>

public abstract class BaseRequestWrapperResponse_Request
{
    public Request Request { get; set; }
}

与泛型类型和有关其泛型类型参数的信息没有任何关系。

如果要访问Request对象,则应将其添加到公共接口,例如IResponse,您的抽象泛型类型随后实现:

public interface IResponse
{
    IRequestFromResponse Request { get; set; }
}

这至少会允许您访问请求对象 - 尽管您可能仍然需要进行转换。

答案 2 :(得分:0)

尝试:

var model = ((ViewContext) context).ViewData.Model;
var modelType = model.GetType();

if (modelType .GetGenericArguments()[0] == typeof (Request)) 
&& 
modelType.GetGenericTypeDefinition().IsAssignableFrom(typeof(BaseRequestWrapperResponse<>)) 
{
    model = ((BaseRequestWrapperResponse<Request>) model).Request;
}

请注意,即使Request继承自IRequestFromResponse,BaseRequestWrapperResponse也不会从BaseRequestWrapperResponse继承,因此您无法做到:

if (modelType .GetGenericArguments()[0].IsAssignableFrom(typeof(IRequestFromResponse)) && 
    modelType.GetGenericTypeDefinition().IsAssignableFrom(typeof(BaseRequestWrapperResponse<>)) 
    {
        model = ((BaseRequestWrapperResponse<IRequestFromResponse>) model).Request;
    }

如果模型的泛型实际上是BaseRequestWrapperResponse