C# Activator.CreateInstance 抽象类找不到构造函数



我试图让多个程序集中命令的每个子级都存储在列表中,但为了做到这一点,我需要创建该子级的实例来存储它,所以我尝试使用Activator.CreateInstance的目标是有一个供外部使用的ctor和一个用于Activator的ctor,这样它就可以创建要存储的实例,问题是Activator由于某种原因找不到ctor,我甚至将ctor标记为public,但运气不佳

public abstract class Command
{
public static List<Command> List { get; set; }
public static Dictionary<Type, int> Lookup { get; set; }
public Command(int id, FieldInfo[] field) 
{
Id = id;
Fields = field;
}
public Command()
{
Command command = List[Lookup[GetType()]];
Id = command.Id;
Fields = command.Fields;
}
public static void Initialize()
{
Lookup = new Dictionary<Type, int>();
List = new List<Command>();
foreach (Type type in
AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes())
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(Command))))
{
Command command = (Command)Activator.CreateInstance(type, List.Count, type.GetFields());
Lookup.Add(type, command.Id);
List.Add(command);
}
}
}
public class PlayerMove : Command
{
}
[TestClass()]
public class PacketTests
{
[TestMethod()]
public void PackTest()
{
Command.Initialize();
Packet packet = new Packet();
var cmd = new PlayerMove()
{
};
cmd.Send(Method.Unreliable);
var g = Command.List;
}

我做错了什么?

您正在尝试构造PlayerMove的实例。它只有一个默认构造函数,即PlayerMove(),它将调用基构造函数Command()。因此,您对Activator.CreateInstance的呼叫应该看起来像

Command command = (Command)Activator.CreateInstance(type);

或者,您应该向PlayerMove类添加一个额外的构造函数:

public class PlayerMove : Command
{
public PlayerMove(int id, FieldInfo[] field) : base(id, field){}
public PlayerMove() : base(){}
}

但我认为你真正想要的可能是这样的东西:

public abstract class Command
{
public static List<Command> List { get; private set; }
public static Dictionary<Type, int> Lookup { get; private set; }
public int Id { get; }
public FieldInfo[] Fields { get; }
protected Command(int id, FieldInfo[] field)
{
Id = id;
Fields = field;
}
protected Command()
{
Command command = List[Lookup[GetType()]];
Id = command.Id;
Fields = command.Fields;
}
public static void Initialize()
{
Lookup = new Dictionary<Type, int>();
List = new List<Command>();
foreach (Type type in
AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes())
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(Command))))
{
Command command = (Command) Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.NonPublic, null,
new object[] {List.Count, type.GetFields()}, null);
Lookup.Add(type, command.Id);
List.Add(command);
}
}
}
public class PlayerMove : Command
{
private PlayerMove(int id, FieldInfo[] field) : base(id, field)
{
}
public PlayerMove()
{
}
}

这为通过反射调用的PlayerMove命令添加了一个私有构造函数,并填充基类上的IdFields属性,以及一个可供该类的其他客户端使用的无参数构造函数。

最新更新