The Factory mode based on C # reflection mechanism

Source: Internet
Author: User

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.