【问题标题】:Any way to get the definition of a property from the code itself?有什么方法可以从代码本身获取属性的定义?
【发布时间】:2018-11-12 14:38:13
【问题描述】:
public abstract class Unit
{
    public abstract List<Move> allowedMoves{get;}
}

public class Javelineer : Unit
{
    public List<Move> allowedMoves =>
        new List<Move> {Move.Impale, Move.JavelinThrow, Move.ShieldBlock};
}

public class Dragon : Unit
{
    public List<Move> allowedMoves =>
        new List<Move> {Move.BreatheFire, Move.Swipe, Move.Bite, Move.Devour, Move.TailBash};
}

X:

鉴于上述代码,我是否以及如何在不必实例化新对象的情况下检索给定单元的允许移动?

我知道我可以使用此代码检索该属性:

typeof(Javelineer).GetProperty("allowedMoves")

但是如果以及如何检索此属性的定义?

Y:

客户端(网络浏览器)必须将玩家单位发送给游戏服务器。这包括单位的类型和该单位能够执行的动作(所有可用的 4 个;类似于口袋妖怪)。

虽然验证(当然)是在服务器上执行的,但浏览器仍然需要获取可用单位类型和允许移动的列表。

为了不重复代码,我想避免在 Javascript 中对这些数据进行硬编码。

读过some excellent SO questions & answers 我想我可以用类似下面的代码检索所有可用的单元:

Assembly.GetExecutingAssembly().GetTypes().Where(
    type => type.BaseType == typeof(Unit)
).Select(type => type.Name).ToList()

我会在服务器启动时调用此代码,缓存结果并将缓存结果发送到每个连接的客户端,因为我觉得调用此代码可能很昂贵。

但是我怎样才能检索允许移动的列表呢?

【问题讨论】:

  • 要获得允许移动的列表,您有 3 个选项。 1)您构造对象的实例并读取属性,或 2)您使用 mono.cecil 或其他一些 IL 检查库并检查 IL,解码指令并模拟运行时。 第二种选择完全不现实。选项 3) 是将可能的移动列表分离成可以通过反射读取的内容。这第三个选项可能不会比选项 1 更好。最重要的是,构建实例。
  • @LasseVågsætherKarlsen 如果您将此作为答案,我会接受。

标签: c# reflection properties system.type


【解决方案1】:

您有两个选择,但 TL;DR:构造对象实例并读取属性。

无论如何,这里有一些选项,有创造力的人可能会找到更多。

  1. 构造实例,读取属性。

    这是代码方面的最佳选择,因为它易于理解、维护和错误修复。

  2. 重写代码以便使用反射轻松检测值

    做到这一点的一种方法是使用属性,用合法移动标记属性或对象。 但是,为了避免出现属性做一件事,代码做另一件事的错误,您可能必须更改代码以同时使用属性,这会影响性能。

    此外,读取这些属性可能会构建比原始对象更多的对象。

  3. 使用mono.cecil 或其他一些IL-inspection 库来解码属性getter 的代码并找到该列表的构造,提取要添加到列表中的值。您基本上要么必须简化该属性的代码以与您现在拥有的相同(并且永远不允许它变得更复杂),要么基本上模拟代码的执行。

    这就像建造一支拥有足够火力的太空战舰舰队来摧毁当地的星系,只是为了杀死一只蚂蚁。

底线,构造对象实例,读取属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-14
    相关资源
    最近更新 更多