Exception Message: Constructor on type StateLog not found
.
I have the following code that does not work for only one class:
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)); } }
The constructor for the class that it does not work for is exactly like the other classes for which it works. The only difference is that this class will be passed 16 arguments instead of 2-5. The constructor looks as such:
public StateLog(string[] line) { try { SessionID = long.Parse(line[0]); AgentNumber = int.Parse(line[1]); StateIndex = int.Parse(line[5]); .... } catch (ArgumentNullException anex) { .... } }
Like I said, it works for the other 5 classes that use this, the only difference is the number of inputs.
That's because you are using the Activator.CreateInstance
overload which accepts an object array, which is supposed to contain a list of constructor parameters. In other words, it's trying to find a StateLog
constructor overload which has 16 parameters, instead of one. This compiles due to array covariance.
So when the compiler sees this expression:
Activator.CreateInstance(typeof(T), lines)
since lines
is a string[]
, it presumes you want to rely on covariance to have it cast it to object[]
automatically, meaning that the compiler actually sees it like this:
Activator.CreateInstance(typeof(T), (object[])lines)
The method will then try to find a constructor which has a number of parameters equal to lines.Length
, all of type string
.
For example, if you have these constructors:
class StateLog { public StateLog(string[] line) { ... } public StateLog(string a, string b, string c) { ... } }
Calling Activator.CreateInstance(typeof(StateLog), new string[] { "a", "b", "c" })
will call the second constructor (the one with three parameters), instead of the first one.
What you actually want is to pass the entire lines
array as the first array item, effectively:
var parameters = new object[1]; parameters[0] = lines; Activator.CreateInstance(typeof(T), parameters)
Of course, you can simply use an inline array initializer:
list.Add((T)Activator.CreateInstance(typeof(T), new object[] { lines }));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With