0

I want to create an array that holds different objects within an inheritance paradigm. I have an item class that several other classes to be inherited. My goal is to put different objects that inherit item into an array. I won't know the type of object and thus will need to instantiate an object of an unknown type.

I've been following this Stackoverflow question: Dynamically create an object of < Type> and different variations of it.

using System;

const int _size= 3;
private Item[] _slots = new Item[_size];


// Method to place objects in array
// item here may be Carrot or Potato or another object
public void AddToBackpack(Item item) {

   // Dynamically create Item object
   var newItem = GetInstance<Item>(item.ToString());

   // Find object in _slots array of similar type and merge newItem with it.

}


public T GetInstance<T>(string type) {
    return (T)Activator.CreateInstance(Type.GetType(type));
}



// Classes
public class Carrot : Item {
    public Carrot() {
        _stackLimit = 5;
    }
}

public class Potato : Item {
    public Potato() {
        _stackLimit = 3;
    }
}

public abstract class Item {
    public int _stackLimit { get; set; } = 1;
    public int _stackSize { get; set; } = 1;
}

Here is the error I'm getting when I try and and call Activator.CreateInstance

Run-time exception (line -1): Request failed.

Stack Trace:

[System.Security.SecurityException: Request failed.]
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at Submission#0.GetInstance[T](String type)
   at Submission#0.<<Initialize>>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.<RunSubmissionsAsync>d__9`1.MoveNext()
ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Regis
  • 166
  • 4
  • 17
  • 2
    Change `GetInstance` to take a `Type` parameter and use `item.GetType()` to get the type to pass to it. `Type.GetType` is ... "tempermental". Plus, using `ToString` on an instance to get the type name works if you haven't overridden `ToString` but it's not the right way to do it if you know you want the type name (use `item.GetType().Name` instead). – madreflection Jun 26 '19 at 17:15
  • Why would your `GetInstance` method both use a generic type parameter for the desired type and also a string with the name of the desired type? One of them is redundant and therefore unnecessary... –  Jun 26 '19 at 17:18
  • 2
    None of this looks right; if you have an instance of `Item` in hand, why are you creating a new one? – Eric Lippert Jun 26 '19 at 17:18
  • @madreflection thanks I'll give that a try. – Regis Jun 26 '19 at 17:19
  • @EricLippert I've removed a bunch of code for simplicity sake. I have to create a new one to accomplish what I'm trying to do. – Regis Jun 26 '19 at 17:20

1 Answers1

0

I am not sure why you use reflection here. Maybe i do not understand your use-case but, You are passing Item item what is Carrot or Potato and then you want to create the same object using reflection... why you just do not use passed instance ?

but to solve your problem try:

// change this method like this 
public void AddToBackpack(Item item) {

   // Dynamically create Item object
   var newItem = GetInstance<Item>(item.GetType());

   // Find object in _slots array of similar type and merge newItem with it.

}

// and this method like this
public T GetInstance<T>(Type type) {
    return (T)Activator.CreateInstance(type);
}

or Make it more generic

// change this method like this 
public void AddToBackpack<T>(T item) where T: Item
 {

   // Dynamically create Item object
   var newItem = GetInstance<T>();

   // Find object in _slots array of similar type and merge newItem with it.

}

// and this method like this
public T GetInstance<T>() {
    return (T)Activator.CreateInstance<T>(); 
}

Peter M.
  • 1,028
  • 2
  • 10
  • 27