在C#中实例化动态类型

时间:2018-11-05 17:27:16

标签: c#

我有一个Animal类和两个派生类:LionAnt

我有一个采用Animal类型的方法,我想返回传递给函数的动物派生类型的新实例(即Lion的新实例)。 / p>

public Animal Reproduce(Animal p_animal)
{
    Type animalType = p_animal.GetType();

    if (SameSpecies(p_animal)) 
        return new animalType(RandomName());
}

3 个答案:

答案 0 :(得分:4)

有几种方法可以实现此目的,但是我建议您在Animal类上创建一个抽象的Reproduce方法,并在派生类型中实现它。例如:

public abstract class Animal
{
    /* .. other stuff .. */
    public abstract Animal Reproduce();
    public string RandomName() { /* ... */ }
}

public class Lion : Animal
{
    /*... other stuff .. */
    public override Animal Reproduce() => new Lion(RandomName());
}

这样,您就可以在特定于特定Reproduce的{​​{1}}方法中添加任何将来的逻辑

答案 1 :(得分:3)

由于您在编译时不知道类型,因此必须使用Reflection。您可以尝试通过以下方法实现目标:

return (Animal)Activator.CreateInstance(animalType, RandomName());

该行在运行时执行,这意味着,如果类型“ animalType”实际上不是类“ Animal”的扩展,则此行将在运行时失败。另外,您的“ animalType”类型的构造函数之一需要恰好接收一个返回“ RandomName()”类型的函数的参数,否则您将遇到运行时错误。

编辑:反射会降低性能,因此应尽可能避免。 KMoussa建议您可以采用一种避免反射的好方法,因此比反射方法好得多。

答案 2 :(得分:0)

您可以使用反射,也可以保持某种类型的安全性,并使用一种称为“好奇地重复的模板模式”的东西。它使用泛型,如果您不熟悉该概念,我会做一些阅读,因为它们在.Net Eco系统中非常强大,有用且普遍。无论如何,这就是我要做的

public abstract class Animal<T> 
    where T : Animal<T>
{
    public string Name {get; private set;}
    public Animal(string name)
    {
        Name = name;
    }

    public abstract T Reproduce();  

    public static T Reproduce(T animalToReproduce)
    {
        return animalToReproduce.Reproduce();
    }

}

public class Lion : Animal<Lion>
{
    public Lion(string name)
        : base (name)
    {

    }
    public override Lion Reproduce()
    {
        return new Lion(RandomName());
    }

}

然后您可以致电Animal.Reproduce(yourAnimalInstance) 这将返回正确类型的对象。例如

Lion myLion = GetALionFromSomewhere();
Lion babyLion = Animal.Reproduce(myLion);

可以编译,并且您具有类型安全性的所有优点