Конструктор по типу не найден

Сообщение об исключении: Constructor on type StateLog not found.

У меня есть следующий код, который не работает только для одного класса:

        List<T> list = new List<T>();
        string line;
        string[] lines;

        HttpWebResponse resp = (HttpWebResponse)HttpWebRequest.Create(requestURL).GetResponse();

        using (var reader = new StreamReader(resp.GetResponseStream()))
        {
            while ((line = reader.ReadLine()) != null)
            {
                lines = line.Split(splitParams);
                list.Add((T)Activator.CreateInstance(typeof(T), lines));
            }
        }

Конструктор для класса, для которого он не работает, точно так же, как и другие классы, для которых он работает. Единственное различие заключается в том, что этому классу будут переданы 16 аргументов вместо 2-5. Конструктор выглядит следующим образом:

    public StateLog(string[] line)
    {
        try
        {
            SessionID = long.Parse(line[0]);
            AgentNumber = int.Parse(line[1]);
            StateIndex = int.Parse(line[5]);
            ....
        }
        catch (ArgumentNullException anex)
        {
            ....
        }
    }

Как я уже сказал, он работает для других 5 классов, которые используют это, единственное различие - это количество входов.

Ответы

Ответ 1

Это потому, что вы используете Activator.CreateInstance overload, который принимает массив объектов, который должен содержать список параметров конструктора. Другими словами, он пытается найти перегрузку конструктора StateLog, которая имеет 16 параметров, а не одну. Это компилируется из-за ковариации массива.

Итак, когда компилятор видит это выражение:

Activator.CreateInstance(typeof(T), lines)

так как lines является string[], он предполагает, что вы хотите полагаться на ковариацию, чтобы автоматически передать его на object[], что означает, что компилятор действительно видит это следующим образом:

Activator.CreateInstance(typeof(T), (object[])lines)

Затем метод попытается найти конструктор, который имеет ряд параметров, равных lines.Length, всех типов string.

Например, если у вас есть эти конструкторы:

class StateLog
{
      public StateLog(string[] line) { ... }
      public StateLog(string a, string b, string c) { ... }
}

Вызов Activator.CreateInstance(typeof(StateLog), new string[] { "a", "b", "c" }) вызовет второй конструктор (тот, у которого три параметра), а не первый.

На самом деле вы хотите передать массив целиком lines в качестве первого элемента массива, эффективно:

var parameters = new object[1];
parameters[0] = lines;
Activator.CreateInstance(typeof(T), parameters)

Конечно, вы можете просто использовать инициализатор встроенного массива:

list.Add((T)Activator.CreateInstance(typeof(T), new object[] { lines }));