我正在尝试使用Activator.CreateInstance创建一个类并将其强制转换为它实现的通用接口。
为什么我在运行时(.Net 4.0)收到'InvalidCastException'?
以下是代码:
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
{
}
}
答案 0 :(得分:1)
你得到的是IActionValidator<IActionSomething>
。无法将IActionValidator<IActionSomething>
分配给IActionValidator<IAction>
,因为T
被标记为in
类型参数。
想象一下,对于名为IActionValidator<IAction>
的{{1}}变量,有以下v
方法:
Validate
现在,如果Validate(IAction action, out string failure);
指向v
的实例,您可以通过IActionValidator<IActionSomething>
将IAction
实例传递给第一个参数,该参数未实现v
}。但是,IActionSomething
确实需要后者。因此,编译器不会让你这样做。
答案 1 :(得分:0)
一种方法是使用dynamic。
dynamic smth = Activator.CreateInstance(typeFromSomewhere);
由于编辑器无法在设计时确定类型,因此您将失去自动完成功能。但是您仍然能够仅通过手工编码来调用方法。
smth.Validate(() => true, "");