[英]Using reflection to create a class that implements an interface of type T
我有一个奇怪的反思问题。
请参阅实现接口IFooAttempt1
的类FooAttempt1
,该接口具有返回IAnimal
的属性。 在FooAttempt1
的情况下,它将返回Dog
。
在所讨论的程序中,将实例化实现IFooAttempt1
的类,进行一些工作,然后将其自身的反射类型和键存储到数据库中,然后使用反射将其重新水化。 有许多实现IFooAttempt1
类,并且它是一种运行良好的体系结构。
您可以在Attempt1()
方法中看到工作的基本过程。
问题在于,实型IFooAttempt1
稍微复杂IFooAttempt1
,并且很容易犯错误。 因此,我们对代码进行了一些重构,以使用泛型来帮助确保正确实现这些类。
请参阅FooAttempt2
,它实现了通用interface IFooAttempt2 < T > where T : IAnimal
。
这样可以确保将Animal属性现在定义为
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>
,其中Dog
是IAnimal
我也无法将其转换为( IFooAttempt2<IAnimal>
)。
我立即想到的是尝试这样做
Type type = assembly.GetType(className, false, true).MakeGenericType(new[] { typeof(IAnimal) });
但它不能编译。 显然,编译器不喜欢typeof(interface)
在这一阶段,我完全陷入困境。
谢谢!
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();
}
}
}
您可以在T
中使IFooAttempt2
协变量:
public interface IFooAttempt2<out T>
where T : IAnimal
{
T Animal
{
get;
}
}
那么对IFooAttempt2<IAnimal>
将成功。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.