简体   繁体   English

在C#中实例化动态类型

[英]Instantiate a dynamic Type in C#

I have an Animal class, and two derived classes: Lion and Ant . 我有一个Animal类和两个派生类: LionAnt

I have a method that takes in an Animal type and I want to return a new instance of the derived type of the animal passed to the function (ie a new instance of Lion ). 我有一个采用Animal类型的方法,我想返回传递给函数的动物派生类型的新实例(即Lion的新实例)。

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

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

There are several ways to achieve this, but what I would suggest is that you create an abstract Reproduce method on your Animal class and implement it in the derived types. 有几种方法可以实现此目的,但是我建议您在Animal类上创建一个抽象的Reproduce方法,并在派生类型中实现它。 For instance: 例如:

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());
}

That way you can add any future logic in the Reproduce method specific to a certain Animal 这样,您可以在特定于特定AnimalReproduce方法中添加任何将来的逻辑

Since you don't know the type at compile time , you will have to use Reflection. 由于您在编译时不知道类型 ,因此必须使用Reflection。 What you are trying to achieve can be done with: 您可以尝试实现以下目标:

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

That line is executed at runtime, meaning that, if the type "animalType" is actually not an extension of the class "Animal", this line will fail at runtime. 该行在运行时执行,这意味着,如果类型“ animalType”实际上不是类“ Animal”的扩展,则此行将在运行时失败。 Also, one of the constructors of your type "animalType" needs to receive exactly one argument of whatever type "RandomName()" function returns, otherwise you will also have a runtime error. 同样,类型为“ animalType”的构造函数之一需要恰好接收一个无论“类型”(RandomName())函数返回的参数,否则您还将遇到运行时错误。

EDIT: Reflection has a performance cost and should be avoided when possible. 编辑:反射会降低性能,应该尽可能避免。 KMoussa suggested a good approach you can follow that avoids reflection and thus is much better than the reflection approach. KMoussa建议您遵循的一种很好的方法可以避免反射,因此比反射方法好得多。

You could use reflection OR you could keep some type safety and use something called the 'Curiously recurring template pattern'. 您可以使用反射,也可以保持某种类型的安全性,并使用一种称为“好奇地重复出现的模板模式”的东西。 It uses generics, if you aren't familiar with that concept, I would do some reading up as they are very powerful, useful and prevalent in the .Net Eco system. 它使用泛型,如果您不熟悉该概念,我会做一些阅读,因为它们在.Net Eco系统中非常强大,有用且普遍。 Any way, here is what I would do 无论如何,这就是我会做的

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());
    }

}

Then you can just call Animal.Reproduce(yourAnimalInstance) this will return an object of the correct type. 然后,您可以只调用Animal.Reproduce(yourAnimalInstance)这将返回正确类型的对象。 For example 例如

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

That will compile and you've got all the goodness of type safety 它将编译,并且您具有类型安全性的所有优点

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM