【问题标题】:Instantiate Dynamic Classes实例化动态类
【发布时间】:2019-11-08 16:53:19
【问题描述】:

我想创建一个数组,在继承范式中保存不同的对象。我有一个 item 类,要继承其他几个类。我的目标是将继承 item 的不同对象放入一个数组中。我不知道对象的类型,因此需要实例化一个未知类型的对象。

我一直在关注这个 Stackoverflow 问题:Dynamically create an object of < Type> 以及它的不同变体。

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;
}

这是我在尝试调用 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()

【问题讨论】:

  • 更改GetInstance 以获取Type 参数并使用item.GetType() 获取要传递给它的类型。 Type.GetType 是……“脾气暴躁”。另外,如果您没有覆盖 ToString,则在实例上使用 ToString 来获取类型名称是有效的,但如果您知道您想要类型名称(使用 item.GetType().Name 代替),这不是正确的方法。
  • 为什么您的GetInstance&lt;T&gt; 方法既要使用所需类型的泛型类型参数,又要使用带有所需类型名称的字符串?其中之一是多余的,因此没有必要......
  • 这些看起来都不对;如果你手头有Item 的实例,你为什么要创建一个新实例?
  • @madreflection 谢谢我试试看。
  • @EricLippert 为了简单起见,我删除了一堆代码。我必须创建一个新的来完成我想做的事情。

标签: c# class


【解决方案1】:

我不确定你为什么在这里使用反射。也许我不理解您的用例,但是,您正在传递 Item item 什么是 CarrotPotato 然后您想使用反射创建相同的对象...为什么您不使用传递的实例?

但要解决您的问题,请尝试:

// 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);
}

或者让它更通用

// 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>(); 
}

【讨论】:

    猜你喜欢
    • 2014-01-26
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多