【问题标题】:C# type of generic class that inherits from abstract class继承自抽象类的泛型类的 C# 类型
【发布时间】:2021-07-05 17:06:46
【问题描述】:

我正在努力寻找一种简单的方法来获取基于从抽象类继承的泛型类的类型。

我有这个层次结构:

public abstract class BaseItemData {}

public abstract class WearableItemData : BaseItemData {}

----
public class EquipmentItemData : WearableItemData {}

public class WeaponItemData : WearableItemData {}

----

public class Item<T> : ScriptableObject {}

public class EquipmentItem : Item<EquipmentItemData> { }

public class WeaponItem : Item<WeaponItemData> { }

有了这个,我想在编辑器时获取所有 Scriptable Objects 资产。 我正在使用 Odin Inspector 构建自定义编辑器,并希望将 Item 类型的所有资产添加到树中 但我不能这样做,因为泛型类型需要传递给Item

   protected override OdinMenuTree BuildMenuTree() {
        OdinMenuTree tree = new OdinMenuTree();
    
    // THIS WORKS
        tree.AddAllAssetsAtPath("TEMPLATES/Weapons", "Assets/Scriptable/Templates", typeof(WeaponItem));
        tree.AddAllAssetsAtPath("TEMPLATES/Equipment", "Assets/Scriptable/Templates", typeof(EquipmentItem));

   // BUT I WOULD LIKE TO HAVE SOMETHING MORE LIKE THIS

        tree.AddAllAssetsAtPath("TEMPLATES", "Assets/Scriptable/Templates", typeof(Item)); // or typeof(Item<WearableItemData>)
    
        return tree;
      }

这些作品

typeof(Item<WeaponItemData>)
typeof(Item<EquipmentItemData>)
typeof(WeaponItem)
typeof(EquipmentItem)

但是这些并不像我想象的那样(显然抽象类不起作用???)

typeof(Item<BaseItemData>)
typeof(Item<WearableItemData>)

我怎样才能使typeof(Item&lt;WearableItemData&gt;) 可以工作? (可能是 Odin 特定的??(编辑时间?))

【问题讨论】:

  • “获取所有对象”是什么意思?你是怎么得到它们的?
  • 我按预期获得了所有类型。也许这个问题需要重新处理
  • 听起来像是 XY 问题。你为什么要使用typeof(Item&lt;WearableItemData&gt;)?您是要获取该可编写脚本对象的所有 assets,还是该可编写脚本对象的所有(运行时)instances?此外,这是否适用于仅应在编辑时使用的代码?还是这段代码需要在游戏中运行?需要更多信息。问题背后的意图过于模糊,无法提供最有用的建议。
  • 忘记链接了:XY problem
  • 我以前从未使用过 odin。这是一种 hack,但是如果你创建一个虚拟类 public class ItemBase : ScriptableObject {/*nothing*/},然后用 public class Item&lt;T&gt; : ItemBase {/*...*/} 从它继承,那么你可以使用 typeof(BaseItem)?我不知道 odin 是如何在后台使用 Type 参数的。

标签: c# unity3d generics inheritance


【解决方案1】:

为所有非泛型的东西创建一个类(或者留空):

public class ItemBase : ScriptableObject 
{
    /* nothing, or non-generic stuff here */
}

然后,从它继承你现在拥有的通用项目:

public class Item<T> : ItemBase 
{
    /*...*/
}

然后,你可以使用tree.AddAllAssetsAtPath("TEMPLATES", "Assets/Scriptable/Templates", typeof(ItemBase));

【讨论】:

  • 实际上根本不是“黑客”.. 当我有泛型基类时,我经常使用它.. 只需将非泛型的所有内容放入非泛型基类中,只放入泛型的东西进入通用的。这种方式模式非常强大..你可以例如只需以这种方式使用Resources.FindObjectsOfTypeAll&lt;ItemBase&gt;(),而无需提供泛型类型;)
  • 是的,它还结合了泛型接口和非泛型基接口.. 相同的原理
  • 顺便说一句,拥有同名的非泛型和泛型类型也是完全合法的,所以在这里例如Item : ScriptaleObjectItem&lt;T&gt; : Item ;)
  • 是的 ^^ 就像我第一次看到这个时一样.. 虽然它是有道理的.. 它基本上与方法重载非常相似.. 它也是所有“重载”发生的唯一情况为我进入同一个脚本文件:'D
  • 这对我来说很有趣,因为你不能在 java 或 c++ 中使用它们的泛型/模板来做到这一点。整洁的东西
猜你喜欢
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多