[英]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.