Home > OS >  How do I create and use a Stack of a type known at runtime
How do I create and use a Stack of a type known at runtime

Time:12-12

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);
}
  •  Tags:  
  • c#
  • Related