Reputation: 2593
I'm trying to create a class using Activator.CreateInstance and cast it to a generic interface it implements.
Why am I getting 'InvalidCastException' at run time (.Net 4.0)?
Here is the code:
namespace CastingGenerics
{
class Program
{
static void Main(string[] args)
{
var typeFromSomewhere = typeof(ActionSomethingValidator);
// This line throw 'System.InvalidCastException'
// "Unable to cast object of type 'CastingGenerics.ActionSomethingValidator' to type 'CastingGenerics.IActionValidator`1[CastingGenerics.IAction]'."
var castingError = (IActionValidator<IAction>)Activator.CreateInstance(typeFromSomewhere);
}
}
internal interface IAction
{
}
internal interface IActionValidator<in T>
where T : IAction
{
bool Validate(T action, out string failure);
}
internal abstract class ActionValidator<T> : IActionValidator<T>
where T : IAction
{
public abstract bool Validate(T action, out string failure);
}
internal class ActionSomethingValidator : ActionValidator<IActionSomething>
{
public override bool Validate(IActionSomething action, out string failure)
{
failure = string.Empty;
return true;
}
}
internal interface IActionSomething : IAction
{
}
}
Upvotes: 4
Views: 1571
Reputation: 1
One way is using dynamic.
dynamic smth = Activator.CreateInstance(typeFromSomewhere);
You will lose the autocomplete feature since the editor cannot determine the type at design time. But you still able to invoke the methods just coding by hand.
smth.Validate(() => true, "");
Upvotes: 0
Reputation: 20731
What you get is an IActionValidator<IActionSomething>
. IActionValidator<IActionSomething>
cannot be assigned to IActionValidator<IAction>
, because T
is marked as an in
type parameter.
Imagine, that for an IActionValidator<IAction>
variable named v
, there is the following Validate
method:
Validate(IAction action, out string failure);
Now, if v
pointed to an instance of IActionValidator<IActionSomething>
, you could pass an IAction
instance to the first parameter via v
that does not implement IActionSomething
. However, exactly the latter would be required for IActionValidator<IActionSomething>
. Therefore, the compiler will not let you do this.
Upvotes: 1