web-dev-qa-db-fra.com

Constructeur sur type introuvable

Message d'exception: Constructor on type StateLog not found.

J'ai le code suivant qui ne fonctionne pas pour une seule classe:

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

Le constructeur de la classe pour laquelle il ne fonctionne pas est exactement comme les autres classes pour lesquelles il fonctionne. La seule différence est que cette classe recevra 16 arguments au lieu de 2-5. Le constructeur ressemble à ceci:

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

Comme je l'ai dit, cela fonctionne pour les 5 autres classes qui l'utilisent, la seule différence est le nombre d'entrées.

25
Jacob Lambert

C'est parce que vous utilisez la surcharge Activator.CreateInstance qui accepte un tableau d'objets, qui est censé contenir une liste de paramètres de constructeur. En d'autres termes, il essaie de trouver une surcharge de constructeur StateLog qui a 16 paramètres, au lieu d'un. Cela se compile en raison de covariance de tablea .

Ainsi, lorsque le compilateur voit cette expression:

Activator.CreateInstance(typeof(T), lines)

puisque lines est un string[], cela suppose que vous voulez vous fier à la covariance pour le convertir automatiquement en object[], ce qui signifie que le compilateur le voit réellement comme ceci:

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

La méthode essaiera alors de trouver un constructeur qui a un nombre de paramètres égal à lines.Length, Tous de type string.

Par exemple, si vous avez ces constructeurs:

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

L'appel de Activator.CreateInstance(typeof(StateLog), new string[] { "a", "b", "c" }) appellera le deuxième constructeur (celui avec trois paramètres), au lieu du premier.

Ce que vous voulez réellement, c'est passer le tableau entier lines comme premier élément du tableau , en fait:

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

Bien sûr, vous pouvez simplement utiliser un initialiseur de tableau en ligne:

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