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
返回一个类型为“你是冠军”的所有类的实例!这就像一个符咒,很容易理解。非常感谢!