Reputation: 55
I'm trying populate the properties of several classes by using to reflection to assign default vaules to all their properties.
This is primarily done by using PropertyInfo.Setvalue(instance, value). I have a problem however when that property has a List of a specific class. I don't know that class type until run time.
To create that list and return to set by SetVaule() I am doing the following:
private static IEnumerable<object> CreateAListContainingOneObject(Type type)
{
var listType = typeof(List<>).MakeGenericType(new Type[] { type });
var generic = Activator.CreateInstance(listType);
var dynamicList = generic as dynamic;
var instance = new MySpecialType();
var instance2 = Activator.CreateInstance(type);
var typecheck = instance.GetType() == instance2.GetType();
dynamicList.Add(instance);
dynamicList.Add(instance2);
return dynamicList;
}
I have tried several options, but the one listed here is particularly interesting because when run the typecheck will be true, and the first Add will work, but the second will fail, telling me "The best overloaded Method 'Add(....)' has some invalid arguments".
PS. The list has to be a List of MyType or else I won't be able to set its value to the property by SetVaule(). Using a new List of object and adding my newly instantiated object of type myType will not work.
Edit: The reason I haven't used a generic method to call where I can instantiate a known type is because I'm doing this on a series of classes that inherit from my base class. They havea variety of properties and I can't know and dont want to write code fro each class and each property it can have. The call originates from something like this:
public static ABaseClass FillObjectWithDefaults(this ABaseClass myObject)
{
var properties = myObject.GetType().GetProperties();
foreach (var p in properties)
{
var value = FindValue(p);
p.SetValue(template, value);
}
return template;
}
Upvotes: 2
Views: 512
Reputation: 16609
You could use a second generic method to help you out, so you don't need to mess around with dynamics and Activation.
This just involves finding the helper method and invoking that to create and add the instance to the list. It also give you the option to invoke it generically.
private static IEnumerable<object> CreateAListContainingOneObject(Type type)
{
var del = typeof(Program).GetMethod("CreateAGenericListContainingOneObject",
BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(type);
return del.Invoke(null, new object[] { }) as IEnumerable<object>;
}
private static List<T> CreateAGenericListContainingOneObject<T>()
where T : new()
{
return new List<T> { new T() };
}
Upvotes: 1
Reputation: 118937
Activator.CreateInstance
returns an object of type Object
so the second Add
can't work.
You can either cast it:
var instance2 = Activator.CreateInstance(type) as MySpecialType;
var instance2 = (MySpecialType)Activator.CreateInstance(type);
Or use dynamic
instead of var
:
dynamic instance2 = Activator.CreateInstance(type);
Personally, I'd probably change the function completely to use a generic type parameter like this:
private static IEnumerable<object> CreateAListContainingOneObject<T>()
{
var listType = typeof(List<>).MakeGenericType(typeof(T));
var generic = Activator.CreateInstance(listType);
var dynamicList = generic as dynamic;
var instance = new MySpecialType();
var instance2 = (T)Activator.CreateInstance(typeof(T));
var typecheck = instance.GetType() == instance2.GetType();
dynamicList.Add(instance);
dynamicList.Add(instance2);
return dynamicList;
}
And call it like this:
var list = CreateAListContainingOneObject<MySpecialType>();
Upvotes: 0