简单介绍

反射提供了描写叙述程序集、模块和类型的对象(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;
} }

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()
{
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";
}
}

代码简单意思一下,详细到游戏肯定有很多其它的属性和方法。

如今出现的要求是依据类名来动态创建对象。

常见的方法就是一堆的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);

Food类中加入实现

  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/

基于C#反射机制的工厂模式的更多相关文章

  1. Java反射机制demo(七)—反射机制与工厂模式

    Java反射机制demo(七)—反射机制与工厂模式 工厂模式 简介 工厂模式是最常用的实例化对象模式. 工厂模式的主要作用就是使用工厂方法代替new操作. 为什么要使用工厂模式?直接new不好吗? 直 ...

  2. Java反射机制在工厂模式中的应用

    在本篇文章中就不详细介绍工厂模式,主要介绍一下反射在工厂模式中的使用,让读者对反射机制带来的好处有更深的认识. 首先看一下简单工厂模式 简单工厂模式(simple factory)是类的创建模式,又叫 ...

  3. Java反射机制与工厂模式

    工厂模式属于创建型模式,它提供了一种创建对象的最佳方式. 它的特点是:客户端的程序类不直接牵扯到对象的实例化管理,只与接口发生关联,通过工厂类获取指定接口的实例化对象. 简单工厂模式如下: inter ...

  4. [Java反射机制]用反射改进简单工厂模式设计

    如果做开发的工作,工厂设计模式大概都已经深入人心了,比较常见的例子就是在代码中实现数据库操作类,考虑到后期可能会有数据库类型变换或者迁移,一般都会对一个数据库的操作类抽象出来一个接口,然后用工厂去获取 ...

  5. Java反射机制在代理模式中的使用

    代理模式的核心思路就是一个接口有两个子类,一个子类完成核心的业务操作,另一个子类完成与核心业务有关的辅助性操作. 代理模式分为静态代理模式和动态代理模式.  静态代理模式: //接口类 interfa ...

  6. Java使用反射机制优化工厂方法

    我先举个例子,有一个接口People,这个接口有一个方法: package com.wjy.reflect; public interface People { public abstract voi ...

  7. 反射vs简单工厂模式

    interface Computer { void printpc(); } class lenovo implements Computer { @Override public void prin ...

  8. IOC的实现原理—反射与工厂模式的结合

    反射机制概念   我们考虑一个场景,如果我们在程序运行时,一个对象想要检视自己所拥有的成员属性,该如何操作?再考虑另一个场景,如果我们想要在运行期获得某个类的Class信息如它的属性.构造方法.一般方 ...

  9. Java反射机制及IoC原理

    一. 反射机制概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义.在java中,只要给定类的名字, 那么就可以通 ...

随机推荐

  1. GO语言学习(十八)Go 语言接口

    Go 语言接口 Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口. 实例 /* 定义接口 */ type interface ...

  2. 国内计算机类期刊 SCI收录:

    国内计算机类期刊 SCI收录: JOURNAL OF COMPUTER SCIENCE AND TECHNOLOGY,计算机科学与技术,英文,双月刊, SCIE 国内计算机类期刊 EI收录: 核心类 ...

  3. noi25 最长最短单词(为什么会出现运行时错误)

    noi25 最长最短单词(为什么会出现运行时错误) 一.总结 一句话总结:比如除以零,数组越界,指针越界,使用已经释放的空间,数组开得太大,超出了栈的范围,造成栈溢出 1.c++报runtime er ...

  4. amazeui学习笔记--css(常用组件6)--图标Icon

    amazeui学习笔记--css(常用组件6)--图标Icon 一.总结 1.关注用法即可:在 HTML 上添加添加 am-icon-{图标名称} class. <span class=&quo ...

  5. 重新启动IIS不重启电脑

      有时候我们在WEB程序如:ASP,中无意中使用到了一个死循环,或者在测试 DLL组件时,挂了.这时候IIS就停止了响应,我们要继续我们的工作啊,重启IIS服务吧. 然而这个进程还在执行,Inter ...

  6. 关于javascript中私有作用域的预解释

    1.如何区分私有变量还是全局变量 1).在全局作用域下声明(预解释的时候)的变量是全局变量 2).在“私有作用域中声明的变量”和“函数的形参”都是私有变量 在私有作用域中,我们代码执行的时候遇到一个变 ...

  7. (转)Windows Server 2012 R2虚拟机自激活(AVMA)技术

    转自: 老丁的技术博客 相信Hyper-v管理员都有这样的经历,安装多台虚拟机后,都要一台一台手工激活,如果虚拟机足够多的话,这是一项很繁琐的工作,但从Windows Server 2012 R2开始 ...

  8. 【Codeforces Round #443 (Div. 2) B】Table Tennis

    [链接] 我是链接,点我呀:) [题意] n个人站在一排. 每次第一个人和第二个人打架. 输的人跑到队列的尾巴去. 然后赢的人继续在队首.和第三个人打. 谁会先赢K次. [题解] 会发现,一轮之后就一 ...

  9. 【例题 6-6 UVA - 679】Dropping Balls

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 直接模拟会超时. 根据奇偶的规律.直接判断会往哪里走就好. 每个二叉树的节点.必然是左边和右边走的次数对半分.->奇数左边多一 ...

  10. swift项目第四天:动态加载控制器

    一:Appdelegate import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate ...