Simple Introduction
Reflection provides an object (type) that describes the assembly, module, and type.
You can use reflection to dynamically create instances of types, bind types to existing objects, or get types from existing objects and invoke their methods or access their fields and properties.
Assume that the attribute is used in the code. can use reflection to access them.
The type information here contains the type of method, variable name. Type and other information.
The factory model based on reflection mechanism
For example, as seen in the game's frequently used drop model, item is a base class that defines some underlying attributes and also defines some abstract methods.
Food and weapon inherit from item. Represents a class of item. The next layer of class defines the detailed item. The code is as follows:
Item.cs
Using unityengine;using System.collections;public abstract class Item { protected string name; protected int level; protected int durability; protected int maxdurability = ten; 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; }}
Food.cs
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 () c11/>{ Debug.Log ("Use weapon" + name);} }
FrozenCarpaccio.cs
public class Frozencarpaccio:food {public Frozencarpaccio () { name = "=frozencarpaccio"; }}
Sword.cs
public class Sword:weapon {public Sword () { name = "Sword"; }}
Code simple meaning, detailed to the game there must be a lot of other properties and methods.
The requirement now is to create objects dynamically based on the class name.
The common method is a bunch of switchcase ....
The following are treated in a reflective manner.
Factory classes such as the following
Using unityengine;using system.collections;using system.collections.generic;using System;public class ItemFactory {PU Blic 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)) {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) A s 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; } }}
The code is easy. Before using the factory, the first thing to do is through reflection. The information of the type is recorded in the corresponding dictionary. It is only possible to invoke the corresponding static method when creating the object.
Test code
Using unityengine;using System.collections;public class Itemgenerator:monobehaviour { itemfactory ItemFactory; Use the this for initialization void Start () { itemfactory.collectallentityclasses (); Itemfactory = new Itemfactory (); } Update is called once per framevoid 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 ();}}}
Execution results
To add a configurable script
The need now is to have a JSON script to configure some of the properties of the item, so the advantage is obvious-flexible!
The contents of the JSON are as follows:
[ { "class": "Frozencarpaccio", "name": "Frozen Carpaccio", "Level": "1", "describe": "It ' s a piece of Frozen Raw meat. The only-to-eat it is by cutting thin slices of it. And this is the IT ' s suprisingly good. " }, { " class ":" Mysterymeat "," name ":" The Mysterymeat "," Level ":" 1 ", " describe": "Eat at your own risk!" },]
The detailed idea is to add a static function to the factory. The configuration properties that are used to load all class. stored in JSON data mode. When creating the corresponding class, use the stored jsondata to assign a value to the corresponding variable.
Join in the factory
public static dictionary<string, jsondata> classinfodict = new dictionary<string, jsondata> ();
The corresponding method
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); }}} } } }
Add a virtual method to the item class to initialize the
public abstract void Initializebyjsondata (Jsondata data);
Food class to join the implementation
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 (); } }
It is assumed that the subclass has a special attribute drug initialization, which can be handled by the override method.
It is also possible to actively match the members of the key and type in the JSON by capturing the variable name of the type by reflection. The SetValue method is then used to assign the value.
Create Fooditem in the factory the corresponding method should be changed slightly.
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; } }
Test code does not change, you can choose to print out the describe to see.
References
Reflection (C # and Visual Basic)-https://msdn.microsoft.com/zh-cn/library/ms173183.aspx
Dynamic load and usage types-https://msdn.microsoft.com/zh-cn/library/k3a58006.aspx
C # Reflection (Reflection)-http://www.runoob.com/csharp/csharp-reflection.html
Explain in detail the reflection mechanism and method in C # programming-http://developer.51cto.com/art/200904/118971_all.htm
litjson-https://lbv.github.io/litjson/
The Factory mode based on C # reflection mechanism