标签:简单介绍 mono code post 反射机制 data .com tps 代码
反射提供了描写叙述程序集、模块和类型的对象(Type 类型)。
能够使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或訪问其字段和属性。
假设代码中使用了特性。能够利用反射来訪问它们。
这里的类型信息包含类型的方法,变量名称。类型等信息。
例如以下图所看到的,游戏中经常使用的掉落物模型,Item是基类,定义了一些基础属性,也定义了一些abstract方法。
Food和Weapon继承自Item。表示一类Item。再下一层的类就定义了详细的Item。代码例如以下:
Item.cs
using UnityEngine; using System.Collections; public abstract class Item { protected string name; protected int level; protected int durability; protected int maxDurability = 10; protected bool isStackable; protected string describe; public string Name { get { return name; } set { name = value; } } public string Level { get { return name; } set { name = value; } } public int Durability { get { return durability; } set { durability = value; } } public abstract void Execute(); public void Upgrade() { level++; } public void Fix() { durability = maxDurability; } public virtual bool IsEquipped() { return false; } }
using UnityEngine; using System.Collections; using System; public class Food : Item { public Food() { isStackable = true; name = "Food"; } public override void Execute() { Debug.Log("Eat " + name); } }
Weapon.cs
using UnityEngine; using System.Collections; using System; public class Weapon : Item { public override void Execute() { Debug.Log("Use Weapon " + name); } }
FrozenCarpaccio.cs
public class FrozenCarpaccio : Food { public FrozenCarpaccio() { name = "=FrozenCarpaccio"; } }
public class Sword : Weapon { public Sword() { name = "Sword"; } }
如今出现的要求是依据类名来动态创建对象。
常见的方法就是一堆的switchcase....
以下用反射的方式来处理。
工厂类例如以下
using UnityEngine; using System.Collections; using System.Collections.Generic; using System; public class ItemFactory { public static Dictionary<string, Type> foodClassesDict = new Dictionary<string, Type>(); public static Dictionary<string, Type> weaponClassesict = new Dictionary<string, Type>(); public static void CollectAllEntityClasses() { foodClassesDict.Clear(); weaponClassesict.Clear(); System.Reflection.Assembly[] AS = System.AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < AS.Length; i++) { Type[] types = AS[i].GetTypes(); for (int j = 0; j < types.Length; j++) { string className = types[j].Name; if (types[j].IsSubclassOf(typeof(Food))) { Debug.Log("Food" + className); foodClassesDict.Add(className, types[j]); } else if (types[j].IsSubclassOf(typeof(Weapon))) { Debug.Log("Weapon" + className); weaponClassesict.Add(className, types[j]); } } } } public static Food CreateFoodByClassName(string name) { Type foodType = null; if (foodClassesDict.TryGetValue(name, out foodType)) { return Activator.CreateInstance(foodType) as Food; } else { return null; } } public static Weapon CreateWeaponByClassName(string name) { Type weaponType = null; if (weaponClassesict.TryGetValue(name, out weaponType)) { return Activator.CreateInstance(weaponType) as Weapon; } else { return null; } } }
代码很easy。在使用工厂之前,首先要通过反射。将类型的信息都记录到相应的Dictionary里面。 创建对象的时候仅仅要调用相应的静态方法就能够了。
測试代码
using UnityEngine; using System.Collections; public class ItemGenerator : MonoBehaviour { ItemFactory itemFactory; // Use this for initialization void Start () { ItemFactory.CollectAllEntityClasses(); itemFactory = new ItemFactory(); } // Update is called once per frame void Update () { if(Input.GetKeyDown(KeyCode.F5)) { MysteryMeat mysteryMeat = ItemFactory.CreateFoodByClassName("MysteryMeat") as MysteryMeat; mysteryMeat.Execute(); } if (Input.GetKeyDown(KeyCode.F6)) { Dagger dagger = ItemFactory.CreateWeaponByClassName("Dagger") as Dagger; dagger.Execute(); } } }
执行结果
如今的需求是,须要用json脚本来配置一些item的属性,这样做的优点是显而易见的 - 灵活!
json的内容例如以下:
[ { "class": "FrozenCarpaccio", "name":"Frozen Carpaccio", "level":"1", "describe":"It‘s a piece of frozen raw meat. The only way to eat it is by cutting thin slices of it. And this way it‘s suprisingly good." }, { "class": "MysteryMeat", "name":"the MysteryMeat", "level":"1", "describe":"Eat at your own risk!" }, ]
详细的思路是在工厂中加入一个静态函数。用于载入全部class的配置属性。用json data的方式存起来。在创建相应类的时候用存好的jsondata来给相应的变量赋值。
在Factory中加入
public static Dictionary<string, JsonData> classInfoDict = new Dictionary<string, JsonData>();
public static void CollectAllItemInfo() { classInfoDict.Clear(); TextAsset[] foodTables = Resources.LoadAll<TextAsset>("Data/Food"); foreach (TextAsset table in foodTables) { string jsonStr = table.text; JsonData content = JsonMapper.ToObject(jsonStr); if (content != null) { foreach (JsonData subclass in content) { if (LitJsonUtil.JsonDataContainsKey(subclass, "class")) { string classname = subclass["class"].ToString(); if (!classInfoDict.ContainsKey(classname)) { classInfoDict.Add(classname, subclass); } } } } } }
在Item类中加入虚方法,用于初始化
public abstract void InitializeByJsonData(JsonData data);
public override void InitializeByJsonData(JsonData data) { if (LitJsonUtil.JsonDataContainsKey(data, "name")) { name = data["name"].ToString(); } if (LitJsonUtil.JsonDataContainsKey(data, "level")) { level = Int32.Parse(data["level"].ToString()); } if (LitJsonUtil.JsonDataContainsKey(data, "describe")) { describe = data["describe"].ToString(); } }
假设子类中有特殊的属性药初始化,能够通过override这种方法来处理。
这里还能够通过反射获取类型的变量名来自己主动匹配json中的key和类型的成员。然后通过SetValue方法来进行赋值。
工厂里面创建FoodItem相应的方法也要略微改一下
public static Food CreateFoodByClassName(string className) { Type foodType = null; if (foodClassesDict.TryGetValue(className, out foodType)) { Food tmp = Activator.CreateInstance(foodType) as Food; tmp.InitializeByJsonData(classInfoDict[className]); return tmp; } else { return null; } }
測试代码不变,能够选择把describe打印出来看看。
反射(C# 和 Visual Basic) - https://msdn.microsoft.com/zh-cn/library/ms173183.aspx
动态载入和使用类型 - https://msdn.microsoft.com/zh-cn/library/k3a58006.aspx
C# 反射(Reflection)- http://www.runoob.com/csharp/csharp-reflection.html
详细解释C#编程中的反射机制与方法 - http://developer.51cto.com/art/200904/118971_all.htm
LitJson - https://lbv.github.io/litjson/
标签:简单介绍 mono code post 反射机制 data .com tps 代码
原文地址:http://www.cnblogs.com/zhchoutai/p/7295992.html