I have a method that creates a Stack
for a type specified at runtime like this
public object CreateStackForType(Type childType)
{
return Activator.CreateInstance(typeof(Stack<>).MakeGenericType(childType));
}
This appears to work to create the Stack
object, but now I don't know how to cast the returned object to a Stack
of the correct type so that I can push elements onto it.
For example
public object FillStack(Type childType, object[] values)
{
object myStack = CreateStackForType(childType);
foreach (object value in values)
{
// I want to push 'value' onto 'myStack', but I don't know how to cast 'myStack'
// I want something like ((Stack<childType>)myStack).Push(value)
}
return myStack;
}
I tried doing ((Stack<object>)myStack).Push(value)
, but that gives tells me "specified cast is not valid".
CodePudding user response:
You could make use of the dynamic
keyword and Convert.ChangeType
method
FillStack(typeof(int), new object[] {1, 2, 3});
/****/
public static object FillStack(Type childType, object[] values)
{
// myStack is a Stack<int> in that instance
dynamic myStack = CreateStackForType(childType);
foreach (object value in values)
{
// val is an int in that instance
dynamic val = Convert.ChangeType(value, childType);
myStack.Push(val);
}
return myStack;
}
CodePudding user response:
public object CreateStackForType(Type childType, out Delegate obj)
{
var instance = Activator.CreateInstance(typeof(Stack<>).MakeGenericType(childType));
obj = Delegate.CreateDelegate(typeof(Action<>).MakeGenericType(childType), instance, "Push");
return instance;
}
public object FillStack(Type childType, object[] values)
{
object myStack = CreateStackForType(childType, out Delegate push);
foreach (object value in values)
push.DynamicInvoke(value);
return myStack;
}
But this is inefficient when add a large amount of data.
If you just want to initialize a stack with an array, this is more effective.
public object FillStack(Type childType, Array values)
{
return Activator.CreateInstance(typeof(Stack<>).MakeGenericType(childType), values);
}