我有一个奇怪的反射问题。使用反射来创建实现类型为T的接口的类
请参阅类FooAttempt1
,该类实现接口IFooAttempt1
,该接口具有返回IAnimal
的属性。在FooAttempt1
的情况下,它返回Dog
。
在有问题的程序中,实现IFooAttempt1
的类会被实例化,做一些工作,然后将它们自己的反射类型和一个键存储到数据库中,然后使用反射进行重新水化。有很多这样的类实现IFooAttempt1
,它是一个工作得很好的体系结构。
您可以在方法Attempt1()
中看到工作中的基本过程。
问题是,真实的类比IFooAttempt1
稍微复杂一些,很容易犯一个错误。因此,我们稍微重构了代码以使用泛型来帮助确保这些类正确实现。
请参阅FooAttempt2
,它实现了一个通用的interface IFooAttempt2 <T> where T : IAnimal
。
这确保了动物属性现在定义为
public Dog Animal
而不是
public IAnimal Animal
两个IFooAttempt1
和IFooAttempt2
在功能上是相同的,但仿制药的这种自我记录功能使得执行我们相当多复杂的类非常简单。
当您参考Attempt2()
代码时,问题就出现了。当使用反射来重建FooAttempt2
行
object o = constructor.Invoke(null);
IFooAttempt2<IAnimal> foo2 = (IFooAttempt2<IAnimal>) o;
显示错误
An unhandled exception of type 'System.InvalidCastException' occurred in
ConsoleApplication1.exe Additional information: Unable to cast object of
type 'ConsoleApplication1.FooAttempt2' to type 'ConsoleApplication1.IFooAttempt2`1
[ConsoleApplication1.IAnimal]'.
我能理解它的点,但你怎么做使用反射呢?
在不久的窗口,如果你去
? o
{ConsoleApplication1.FooAttempt2}
Animal: {ConsoleApplication1.Dog}
所以它正确地反映。即使FooAttempt2
被定义为IFooAttempt2<Dog>
,我也不能将它投射到(IFooAttempt2<IAnimal>
),其中Dog
是IAnimal
。
我马上想到,试图做到这一点
Type type = assembly.GetType(className, false, true).MakeGenericType(new[] { typeof(IAnimal) });
但它不会编译。显然编译器不喜欢在这个阶段我完全卡住了。
谢谢!
class Program
{
static void Main(string[] args)
{
Attempt1();
Attempt2();
}
static void Attempt1()
{
FooAttempt1 foo = new FooAttempt1();
Console.WriteLine(foo.Animal.MakeNoise());
string className = foo.GetType().FullName;
// -----
// get the assembly
Assembly assembly = typeof(FooAttempt1).Assembly;
// get the class
Type type = assembly.GetType(className, false, true);
// create an instance
ConstructorInfo constructor = type.GetConstructor(new Type[] { });
IFooAttempt1 foo2 = (IFooAttempt1)constructor.Invoke(null);
Console.WriteLine(foo2.Animal.MakeNoise());
}
static void Attempt2()
{
FooAttempt2 foo = new FooAttempt2();
Console.WriteLine(foo.Animal.MakeNoise());
string className = foo.GetType().FullName;
// -----
// get the assembly
Assembly assembly = typeof(FooAttempt2).Assembly;
// get the class
Type type = assembly.GetType(className, false, true);
// create an instance
ConstructorInfo constructor = type.GetConstructor(new Type[] { });
object o = constructor.Invoke(null);
IFooAttempt2<IAnimal> foo2 = (IFooAttempt2<IAnimal>) o; // << PROBLEM HERE
Console.WriteLine(foo2.Animal.MakeNoise());
}
}
public interface IAnimal
{
string MakeNoise();
}
public class Dog : IAnimal
{
public string MakeNoise()
{
return "Bark";
}
}
public interface IFooAttempt1
{
IAnimal Animal
{
get;
}
}
public class FooAttempt1 : IFooAttempt1
{
public FooAttempt1()
{
}
public IAnimal Animal
{
get
{
return new Dog();
}
}
}
public interface IFooAttempt2<T>
where T : IAnimal
{
T Animal
{
get;
}
}
public class FooAttempt2 : IFooAttempt2<Dog>
{
public FooAttempt2()
{
}
public Dog Animal
{
get
{
return new Dog();
}
}
}
写得不错的问题,更多这些请! – aevitas