wake-up-neo.com

Konstruktor für Typ nicht gefunden

Ausnahmemeldung: Constructor on type StateLog not found.

Ich habe den folgenden Code, der nicht nur für eine Klasse funktioniert:

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

Der Konstruktor für die Klasse, für die er nicht funktioniert, entspricht genau den anderen Klassen, für die er funktioniert. Der einzige Unterschied besteht darin, dass dieser Klasse 16 Argumente anstelle von 2-5 übergeben werden. Der Konstruktor sieht so aus:

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

Wie gesagt, es funktioniert für die anderen 5 Klassen, die dies verwenden, der einzige Unterschied ist die Anzahl der Eingaben.

25
Jacob Lambert

Das liegt daran, dass Sie die Überladung Activator.CreateInstance verwenden, die ein Objektarray akzeptiert, das eine Liste von Konstruktorparametern enthalten soll. Mit anderen Worten, es wird versucht, eine StateLog -Konstruktorüberladung zu finden, die 16 statt einer Parameter enthält. Dies wird aufgrund von Array-Kovarianz kompiliert.

Wenn der Compiler diesen Ausdruck sieht:

Activator.CreateInstance(typeof(T), lines)

da lines ein string[] ist, wird davon ausgegangen, dass Sie sich auf die Kovarianz verlassen möchten, damit es automatisch in object[] umgewandelt wird. Dies bedeutet, dass der Compiler es tatsächlich so sieht:

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

Die Methode versucht dann, einen Konstruktor zu finden, der eine Reihe von Parametern aufweist, die gleich lines.Length Sind und alle den Typ string haben.

Wenn Sie beispielsweise folgende Konstruktoren haben:

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

Durch Aufrufen von Activator.CreateInstance(typeof(StateLog), new string[] { "a", "b", "c" }) wird der zweite Konstruktor (der mit den drei Parametern) anstelle des ersten aufgerufen.

Was Sie tatsächlich wollen, ist, das gesamte Array lines als erstes Array-Element zu übergeben:

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

Natürlich können Sie einfach einen Inline-Array-Initialisierer verwenden:

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