[英]Using reflection to create a class that implements an interface of type T
I have a strange reflection problem. 我有一个奇怪的反思问题。
Refer to the class FooAttempt1
that implements the interface IFooAttempt1
which has a property that returns an IAnimal
. 请参阅实现接口IFooAttempt1
的类FooAttempt1
,该接口具有返回IAnimal
的属性。 In the case of FooAttempt1
it is returning a Dog
. 在FooAttempt1
的情况下,它将返回Dog
。
In the program in question, our classes that implement IFooAttempt1
are instantiated, do some work and then store their own reflected type and a key to the database and are later rehydrated using reflection. 在所讨论的程序中,将实例化实现IFooAttempt1
的类,进行一些工作,然后将其自身的反射类型和键存储到数据库中,然后使用反射将其重新水化。 There are many such classes that implement IFooAttempt1
and it is an architecture that is working quite well. 有许多实现IFooAttempt1
类,并且它是一种运行良好的体系结构。
You can see the basic process at work in the method Attempt1()
. 您可以在Attempt1()
方法中看到工作的基本过程。
The problem is that that real classes are slightly more complex than IFooAttempt1
and it is easy to make a mistake. 问题在于,实型IFooAttempt1
稍微复杂IFooAttempt1
,并且很容易犯错误。 As such we have refactored the code slightly to use generics to help ensure that these classes are implemented correctly. 因此,我们对代码进行了一些重构,以使用泛型来帮助确保正确实现这些类。
Refer to FooAttempt2
which implements a generic interface IFooAttempt2 < T > where T : IAnimal
. 请参阅FooAttempt2
,它实现了通用interface IFooAttempt2 < T > where T : IAnimal
。
This ensures that the Animal property is now defined as 这样可以确保将Animal属性现在定义为
public Dog Animal
rather than 而不是
public IAnimal Animal
Both IFooAttempt1
and IFooAttempt2
are functionally identical but this self-documenting feature of generics makes implementing our rather more complex classes very simple. IFooAttempt1
和IFooAttempt2
在功能上是相同的,但是泛型的这种自记录功能使实现我们相当复杂的类非常简单。
The problem comes when you refer to the Attempt2()
code. 当您引用Attempt2()
代码时,就会出现问题。 When using reflection to recreate FooAttempt2
the line 使用反射重新创建FooAttempt2
,
object o = constructor.Invoke(null);
IFooAttempt2<IAnimal> foo2 = (IFooAttempt2<IAnimal>) o;
displays the error 显示错误
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]'.
I can understand its point but how do you do this using reflection? 我能理解它的意思,但是如何使用反射来做到这一点呢?
In the immediate window, if you go 在即时窗口中,如果您转到
? o
{ConsoleApplication1.FooAttempt2}
Animal: {ConsoleApplication1.Dog}
so it has reflected correctly. 因此已正确反映。 I just can't cast it to a ( IFooAttempt2<IAnimal>
) even though FooAttempt2
is a defined as IFooAttempt2<Dog>
where Dog
is an IAnimal
. 即使FooAttempt2
被定义为IFooAttempt2<Dog>
,其中Dog
是IAnimal
我也无法将其转换为( IFooAttempt2<IAnimal>
)。
My immediate thought was to try to do this 我立即想到的是尝试这样做
Type type = assembly.GetType(className, false, true).MakeGenericType(new[] { typeof(IAnimal) });
but it does not compile. 但它不能编译。 Evidently the compiler does not like the typeof(interface)
显然,编译器不喜欢typeof(interface)
At this stage I am totally stuck. 在这一阶段,我完全陷入困境。
Thanks! 谢谢!
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();
}
}
}
You can make IFooAttempt2
covariant in T
: 您可以在T
中使IFooAttempt2
协变量:
public interface IFooAttempt2<out T>
where T : IAnimal
{
T Animal
{
get;
}
}
then the cast to IFooAttempt2<IAnimal>
will succeed. 那么对IFooAttempt2<IAnimal>
将成功。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.