When I use reflection in this case, the created type can be many generic types.
BaseStepHandler<BaseStepDataModel> activator = (BaseStepHandler<BaseStepDataModel>)Activator.CreateInstance(....);
The created instance can be all childs of BaseStepDataModel.
BaseStepHandler<OneDataModel>
OR
BaseStepHandler<TwoDataModel>
OneDataModel and TwoDataModel are extending BaseStepDataModel.
this is the exception that I get:
Unable to cast object of type ‘….GlobalOnBoardingStepOneHandler’ to type ‘….BaseStepHandler`1[….BaseStepDataModel]’.
this is the declaration if GlobalOnBoardingStepOneHandler.
public class GlobalOnBoardingStepOneHandler : BaseStepHandler<GlobalOnBoardingStepOneDataModel>{}
You are getting the exception because
GlobalOnBoardingStepOneHandlerinherits fromBaseStepHandler<GlobalOnBoardingStepOneDataModel>, notBaseStepHandler<BaseStepDataModel>. This is probably the most common mistake with .NET generics. Generics are not covariant for type parameters.See:
C#: cast to generic interface with base type
http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx
http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-one.aspx
http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-two.aspx
http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx
http://blogs.msdn.com/b/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx
etc…
The issue is that you assume that because
GlobalOnBoardingStepOneDataModelinherits fromBaseStepDataModel, thatGlobalOnBoardingStepOneHandlerinherits fromBaseStepHandler<BaseStepDataModel>. That simply isn’t the case, and so you can’t cast from one to the other.As an example, consider the following:
Now, this is very confusing for recovering Java programmers because this is possible in Java. In Java, you have type erasure, so that at runtime a
List<String>is actually just aList<Object>, and so you can cast it to anything you like, and put anything you want into it. Because the CLR uses reified generics, not type erasure, aList<String>is actually a separate and distinct type from aList<Object>or aList<Integer>