C# Абстрактный класс Activator.CreateInstance не может найти конструктор - PullRequest
0 голосов
/ 06 мая 2020

Я пытаюсь заставить каждого дочернего элемента команд в нескольких сборках хранить их в списке, но для этого мне нужно создать экземпляр этого дочернего элемента, чтобы сохранить его, но поэтому я пытаюсь использовать Activator .CreateInstance цель состоит в том, чтобы иметь ctor publi c для внешнего использования и ctor для Activator, чтобы он мог создавать экземпляры для хранения, но проблема в том, что Activator просто не может найти ctor по какой-то причине, я даже пометил ctor as publi c но не повезло

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

Что я делаю не так?

1 Ответ

0 голосов
/ 06 мая 2020

Вы пытаетесь создать экземпляр 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(){}
}

Но я думаю, что, вероятно, вы на самом деле want - это что-то вроде этого:

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, которая вызывается через отражение и заполняет свойства Id и Fields в базовом классе, а также без параметров конструктор, который затем может использоваться другими клиентами класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...