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:
客户端(Web 浏览器(必须向游戏服务器发送玩家的单位。这包括该单元的类型和该单元能够执行的移动(所有可用中的 4 个;类似于口袋妖怪(。
虽然验证(当然(是在服务器上执行的,但浏览器仍然需要获取可用单位类型和允许移动的列表。
为了不重复代码,我想避免在Javascript中硬编码这些数据。
阅读了一些优秀的SO问题和答案后,我想我可以使用类似于以下内容的代码检索所有可用单元:
Assembly.GetExecutingAssembly().GetTypes().Where(
type => type.BaseType == typeof(Unit)
).Select(type => type.Name).ToList()
我会在服务器启动时调用此代码,缓存结果并将缓存的结果发送到每个连接客户端,因为我觉得调用此代码可能很昂贵。
但是,如何检索允许的移动列表?
你有几个选择,但是TL;DR:构造对象实例并读取属性。
无论如何,这里有一些选择,创造性的头脑可能会找到更多的选择。
-
构造实例,读取属性。
这是代码方面的最佳选择,因为它易于理解、维护和错误修复。
-
重写代码以允许使用反射轻松检测值
一种方法是使用属性,用合法的动作标记属性或对象。但是,为了避免出现属性执行一件事,代码执行另一操作的错误,您可能必须更改代码以使用属性,这将影响性能。
此外,读取这些属性可能会构造比原始对象更多的对象。
-
使用 mono.cecil 或其他一些 IL 检查库来解码属性获取者的代码并查找该列表的构造,提取要添加到列表中的值。基本上,您要么必须将该属性的代码简化以与您现在拥有的代码相提并论(并且永远不允许它变得更加复杂(,要么基本上模拟代码的执行。
这就像建造一支拥有足够火力的太空战舰舰队来摧毁当地的恒星系统,只是为了杀死一只蚂蚁。
底线,构造对象实例,读取属性。