C# 使用反射动态实例化扩展基类的类

C# 使用反射动态实例化扩展基类的类,c#,.net,reflection,system.reflection,decoupling,C#,.net,Reflection,System.reflection,Decoupling,很长一段时间以来,我一直在努力寻找一种方法来动态实例化扩展特定基类的所有类(在运行时)。从我所读到的内容来看,它应该使用反射来完成,不幸的是,我还没有弄清楚如何完成 我的项目结构如下所示: Library --| | --Vehicle.cs (abstract class) | --Car.cs (extending vehicle) | --Bike.cs (extending vehicle) | --Scooter.cs (extending vehicl

很长一段时间以来,我一直在努力寻找一种方法来动态实例化扩展特定基类的所有类(在运行时)。从我所读到的内容来看,它应该使用
反射来完成,不幸的是,我还没有弄清楚如何完成

我的项目结构如下所示:

Library
--|
  |
  --Vehicle.cs (abstract class)
  |
  --Car.cs (extending vehicle)
  |
  --Bike.cs (extending vehicle)
  |
  --Scooter.cs (extending vehicle)
  |
  --InstanceService.cs (static class)
  |
  |
ConsoleApplication
--|
  |
  --Program.cs
InstanceService类包含一个泛型方法,该方法应返回一个
IEnumerable
,其中包含扩展
Vehicle
的实例化类,意思是
汽车、自行车和滑板车

下面的代码是InstanceService类的当前状态,在尝试了大量不同的解决方案之后,这意味着它主要包含调试工具

InstanceService.cs

using System;
using System.Collections.Generic;

namespace Library
{
    public static class InstanceService<T>
    {
        //returns instances of all classes of type T
        public static IEnumerable<T> GetInstances()
        {

            var interfaceType = typeof(T);
            List<T> list = new List<T>();
            Console.WriteLine("Interface type: " + interfaceType.ToString());
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach(var assembly in assemblies)
            {
                Console.WriteLine("Assembly: " + assembly.ToString());
                if (assembly.GetType().IsAbstract)
                {
                    var instance = (T) Activator.CreateInstance(assembly.GetType());
                    list.Add(instance);
                }
            }
            return list;
        }
    }
}
namespace Library
{
    public abstract class Vehicle
    {
        protected float maxSpeedInKmPerHour;
        protected float weightInKg;
        protected float priceInDkk;
    }
}
namespace Library
{
    public class Car : Vehicle
    {

        public Car()
        {
            this.maxSpeedInKmPerHour = 1200;
            this.weightInKg = 45000;
            this.priceInDkk = 71000000;
        }
    }
}
Car.cs

using System;
using System.Collections.Generic;

namespace Library
{
    public static class InstanceService<T>
    {
        //returns instances of all classes of type T
        public static IEnumerable<T> GetInstances()
        {

            var interfaceType = typeof(T);
            List<T> list = new List<T>();
            Console.WriteLine("Interface type: " + interfaceType.ToString());
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach(var assembly in assemblies)
            {
                Console.WriteLine("Assembly: " + assembly.ToString());
                if (assembly.GetType().IsAbstract)
                {
                    var instance = (T) Activator.CreateInstance(assembly.GetType());
                    list.Add(instance);
                }
            }
            return list;
        }
    }
}
namespace Library
{
    public abstract class Vehicle
    {
        protected float maxSpeedInKmPerHour;
        protected float weightInKg;
        protected float priceInDkk;
    }
}
namespace Library
{
    public class Car : Vehicle
    {

        public Car()
        {
            this.maxSpeedInKmPerHour = 1200;
            this.weightInKg = 45000;
            this.priceInDkk = 71000000;
        }
    }
}

这应该适用于可以使用默认构造函数实例化的任何类型。你的类是从另一个类派生出来的这一事实是无关紧要的,除非我遗漏了什么

private T MakeInstance<T>()
{
    // the empty Type[] means you are passing nothing to the constructor - which gives
    // you the default constructor.  If you need to pass in an int to instantiate it, you
    // could add int to the Type[]...
    ConstructorInfo defaultCtor = typeof(T).GetConstructor(new Type[] { });

    // if there is no default constructor, then it will be null, so you must check
    if (defaultCtor == null)
        throw new Exception("No default constructor");
    else
    {
        T instance = (T)defaultCtor.Invoke(new object[] { });   // again, nothing to pass in.  If the constructor needs anything, include it here.
        return instance;
    }
}
private T MakeInstance()
{
//空类型[]表示您没有向构造函数传递任何内容-构造函数
//您可以使用默认构造函数。如果需要传入int来实例化它,您可以
//无法将int添加到类型[]。。。
ConstructorInfo defaultCtor=typeof(T).GetConstructor(新类型[]{});
//如果没有默认构造函数,那么它将为null,因此必须进行检查
if(defaultCtor==null)
抛出新异常(“无默认构造函数”);
其他的
{
T instance=(T)defaultCtor.Invoke(new object[]{});//同样,没有要传递的内容。如果构造函数需要任何内容,请将其包含在此处。
返回实例;
}
}

我认为你应该感兴趣的方法是

此外,如果允许您使用LINQ,那么使用LINQ的代码要容易得多,而且由于您一次创建一个对象,我建议使用


当前的方法(具体地)出了什么问题?没有什么特别的,至少没有返回任何错误。我只是好奇如何以最好的方式实现这一点。此外,在当前的方法中,函数似乎只返回一个无法循环的对象,而实际上它应该返回一个列表,其中包含从
车辆
派生的3个实例化类。然后我在函数返回的列表中使用
ToString()
,我得到以下输出
System.Collections.Generic.List1[Library.Vehicle]
,但使用这种方法,您似乎只创建了一个实例?当我创建从基类派生的所有类的实例时,我认为方法有点不同?是的,这会创建一个实例。如果需要一个特定类型的多个实例,可以在循环中运行它,并在实例化时将它们添加到集合中。我不太确定你在这里要做什么-如果你想要每一个新的,那么John Wu的方法会更好,但是除非你不断地添加类,否则我会手动实例化每一个类,并避免使用反射和泛型,比如InstanceService(这两种方法都是为在编译时不知道所需数据类型的情况而设计的-听起来像是预先知道的)是的,这是正确的。但是这与我想要的无关,因为这是一个赋值,而不是实际的应用程序。在赋值中指定了以下内容:使用方法
IEnumerable GetInstances()创建InstanceService
返回一个类型为“你是冠军”的所有类的实例!这就像一个符咒,很容易理解。非常感谢!