I am working on a project where I am sending commands to a device. Each command object has a one-to-one relationship to a specific command supported by the device (which are defined by the API of a supporting dll).
I have XML files which define the commands: name the method name, and parameters (by name, type, and default value).
My application reads the XML and creates a command object. I have a parameter dictionary which has parameter names associated to values (by type).
When populating the parameter dictionary I started out creating a type, then an instance, then updating the dictionary.
{
theType = Type.GetType(paramType);
var newInstance = Activator.CreateInstance(theType, true);
parameterValueMap.Add(paramName, newInstance);
}
This works fine for ints, etc, but doesn't work for string types, as they don't have a parameterless constructor.
As there may be other types with parameterless constructors, I need to keep the solution generic (not handle strings specifically).
Can somebody help me with the solution? Is there a way to create an instance of a type with parameters without having an actual instance of the parameter (and instance of string in my specific case)?
Thanks -m
Since you mention generics, a default(T)
may be useful, but that will be null
for classes / interfaces. A handy evil trick is:
T obj = (T)FormatterServices.GetUninitializedObject(typeof(T));
However! This is pure evil, usually reserved for deserialization / materialization libraries. This is not intended for ad-hoc usage.
Perhaps the best approach is to let the caller tell you how, for example add an optional factory parameter:
void YourMethod<T>(..., Func<T> constructor = null)
Then if they want the caller can supply a technique to create instances. So you have:
T obj = constructor == null ? (T)Activator.CreateInstance(typeof(T))
: constructor();
In any event: strings are a huge problem. You will undoubtably need to special-case strings.
I use a Activator.CreateInstance(type, ParseKeys(ID).ToArray())
in my code, where ID
is a ||
separated list of key/value pairs, and ParseKeys()
is
private static IEnumerable<object> ParseKeys(string keyString)
{
IEnumerable<string> keyStrings = keyString.Split(new string[] { "||" }, StringSplitOptions.RemoveEmptyEntries); // Use this construction to enable splitting on multiple characters
List<object> keys = new List<object>();
foreach (var key in keyStrings)
{
var type = Type.GetType(key.Split("|")[0]);
var value = key.Split("|")[1];
var data = Convert.ChangeType(value, type);
keys.Add(data);
}
return keys;
}
Obviously, you need to be able to represent your parameters as a string in some form, and I haven't tested it for parameterless constructors, but it works just fine for both ints and strings.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.