How to check if an object inherits from a common base class without knowing the typeparam
I have the following construct for classes:
public class Request : BaseRequest, IRequestFromResponse
{
}
which defines the object Request
to be submitted via the html form.
Model
where Request
lives in build up, for example:
public class Response : BaseRequestWrapperResponse<Request>
{
}
and BaseWrapper:
public abstract class BaseRequestWrapperResponse<TRequest> where TRequest : IRequestFromResponse
{
public TRequest Request { get; set; }
}
IRequestFromResponse
is just an empty marker interface.
I am trying to start an object at runtime, so I have access to Request
-property BaseRequestWrapperResponse
.
All I have so far:
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;
}
I can't get a check that indicates that Model
is kind BaseRequestWrapperResponse
. Then throwing will be my next problem.
source to share
How to add a non-generic class 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; }
}
}
Then just:
model = ((BaseRequestWrapperResponse) model).Request;
source to share
This doesn't work because the only types the model is in are Response
and BaseRequestWrapperResponse<Request>
.
You must understand that generic types are concrete types as soon as you insert a type argument. Since it Request
inherits from BaseRequestWrapperResponse<Request>
, this BaseRequestWrapperResponse<Request>
is an actual type that has no inheritance relationship to BaseRequestWrapperResponse<TRequest>
. Its just kind - a copy with a type argument put it in.
You might see generic types more as templates for actual types that are created when you type in a generic type. So when you used BaseRequestWrapperResponse<Request>
, you actually defined the following type:
public abstract class BaseRequestWrapperResponse_Request
{
public Request Request { get; set; }
}
And there is nothing to do with the generic type and information about its generic type argument.
If you want to access an object Request
, you have to add it to the generic interface eg. IResponse
which then implements your abstract generic type:
public interface IResponse
{
IRequestFromResponse Request { get; set; }
}
This will at least allow you to access the request object, although you will have to use it anyway.
source to share
Try:
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;
}
Note that BaseRequestWrapperResponse does not inherit from BaseRequestWrapperResponse even though Request inherits from IRequestFromResponse, so you cannot do:
if (modelType .GetGenericArguments()[0].IsAssignableFrom(typeof(IRequestFromResponse)) &&
modelType.GetGenericTypeDefinition().IsAssignableFrom(typeof(BaseRequestWrapperResponse<>))
{
model = ((BaseRequestWrapperResponse<IRequestFromResponse>) model).Request;
}
if the generic model is actually BaseRequestWrapperResponse
source to share