使用Reflection获取类型来转换通用对象

时间:2016-10-20 14:16:33

标签: c# .net generics reflection xamarin

我试图在我需要的通用对象中强制转换对象  动态更改类型

Dog<T>继承Animal 上课&#34; T&#34;必须从EntityBase继承 例如,Chihuahua继承EntityBase

for (int i = 0; i < list.Count(); i++){
if (list?.ElementAt(i)?.GetType().GetTypeInfo().BaseType == typeof(Animal))
{
var type = list.ElementAt(i).GetType();
// is wrong, must use a class no a type
//var animal = list.ElementAt(i) as GenericObject< Dog<type >> 
//Correct syntax but cast results null
var animal = list.ElementAt(i) as GenericObject< Dog<EntityBase>> 
//animal is null
DoStuff(animal);
}

如果我使用下一个代码

if (list?.ElementAt(i)?.GetType() == typeof(Dog<Chihuahua>))
   {   
   DoStuff(list.ElementAt(i) as Dog<Chihuahua>);
   }

我想做到最通用的,非常感谢!

我将分享我在完成时所做的项目!

1 个答案:

答案 0 :(得分:4)

将单个列表保存为不同类型的相关类型的能力称为协方差(Contravariance也相关)。这是在.Net中分别用out和in keywoards实现的。使用.net 4.5,协方差内置于IEnumerable&lt; T&GT; 。 IEnumerable的&LT; T&GT;由IList实现&lt; T&GT;这是由List&lt; T&GT ;.

如果您有动物列表,可以在列表中添加任何动物子类型。然而,当你把那只动物拿出来时,在代码中,你得到一个动物类型的变量,指向你的动物亚型。所以看起来你只有一只动物,但它确实是一种亚型。您可以尝试按照建议手动投射所有内容。

还有另一种解决方法(.net 4.5),您可以使用dynamic关键字在运行时确定类型。然后重载DoStuff方法,它应该按照你想要的方式运行。

body, html {
    background-color: blue;
}

.foo { order: 2; }
.bar { order: 1; }


@media only screen and (min-width: 769px) {
    body, html {
        background-color: red;
    }

    .foo { order: 1; }
    .bar { order: 2; }
}

这是输出

public class Animal
{
    public string Name;
    public Animal() { Name = "Animal"; }
}

public class Dog:Animal
{
    public Dog() { Name = "Dog"; }
}

[TestMethod]
public void Test()
{
    var list = new List<Animal>();
    list.Add(new Dog());
    list.Add(new Animal());
    foreach(dynamic a in list)
    {
        DoStuff(a);
    }
}

public void DoStuff(Animal animal)
{
    Console.WriteLine("{0} is wild", animal.Name);
}

public void DoStuff(Dog dog)
{
    Console.WriteLine("{0} is not wild", dog.Name);
}

协方差和逆变是一个复杂的主题。看看这些其他帖子。 Difference between Covariance & Contra-variance Difference between covariance and upcasting