在設計程序時,無論是界面或是後台代碼,我們通常都想留給用戶一個較為簡單的接口。而我在參與封裝語音卡開發函數包的時候,發現各種語音卡的底層函數的接口都是各種整形變量標記值,使用起來極為不變。於是就理解了前輩所寫的代碼中,利用XML構建反射表機制的初衷。下面我就以某一種語音卡所能兼容的語音格式為例,將反射表機制的原理做個示范。
語音卡的底層開發函數中,放音和錄音函數的參數都是很多而且不易理解和記憶的。以語音格式為例,假如a率的標記值是6,u率的標記值是7,……,一般所能兼容的語音格式為10多個。如果我們選用整形變量來做標記語音格式的參數,那麼我們大概就有兩種選擇:1.要麼我們把這種對應關系生記下來,2.要麼我們在調用函數時去查一下對照表,而這兩種方式,都需要做不必要的投入。
這時反射表的優勢就表現出來了,下面看看例子:
//先做一個語音格式的枚舉,方便用戶調用:
enum 語音格式
{
未定義 = -1,
a率 = 0,
u率 = 1,
PCM16 = 2,
PCM8 = 3,
GSM = 4,
ADPCM = 5,
VOX = 6,
MP3 = 7,
G729 = 8,
G723 = 9,
GC8 = 10,
}
//這是一個語音格式類,用於填充語音格式對照表
class PhoneticMatrix
{
XmlNodeList nodeList = null;
XmlNode node=null;
//填充語音格式對照表
public readonly Dictionary<語音格式, int> 語音格式對照表 = new Dictionary<語音格式, int>();
public void FillDirectory(string 配置文件名)
{
XmlDocument xDoc = new XmlDocument();
xDoc.Load(配置文件名);
//選擇格式“結點”列表
nodeList = xDoc.SelectNodes("/語音格式/格式");
foreach(XmlNode nodes in nodeList)
{
//選取結點“名稱”,並讀取結點值
node=nodes.SelectSingleNode("名稱");
string s名稱=node.FirstChild.Value;
//選取結點“編號”,並讀取結點值
node = nodes.SelectSingleNode("編號");
string s編號 = node.FirstChild.Value;
int i編號 = int.Parse(s編號);
//填充語音格式對照表
語音格式 當前語音格式 = (語音格式)Enum.Parse(typeof(語音格式), s名稱);
語音格式對照表.Add(當前語音格式, i編號);
}
}
//編寫一個方法,用來演示語音格式對照表的使用,具體使用方法類似但要視情況而定
//顯示所選取的語音格式的配置編號
public int ShowFormatID(語音格式 用戶選項)
{
int i語音格式編號;
//查詢選定的枚舉項所對應的配置值
語音格式對照表.TryGetValue(用戶選項, out i語音格式編號);
Console.WriteLine("用戶選定項:"+用戶選項.ToString()+";該選項所對應的配置值為:"+i語音格式編號.ToString());
return i語音格式編號;
}
//最後貼出測試用的Main函數
class Program
{
static void Main(string[] args)
{
//獲取當前工作目錄
string dir = Directory.GetCurrentDirectory();
//生成文件路徑
string actualDir = dir + "\語音格式.xml";
PhoneticMatrix pm = new PhoneticMatrix();
pm.FillDirectory(actualDir);
int i格式編號 = pm.ShowFormatID(語音格式.a率);
Console.ReadLine();
}
}
//最後給出測試用的XML文件:
<?xml version="1.0" encoding="utf-8" ?>
<語音格式>
<格式>
<名稱>a率</名稱>
<編號>6</編號>
</格式>
<格式>
<名稱>u率</名稱>
<編號>7</編號>
</格式>
<格式>
<名稱>GSM</名稱>
<編號>49</編號>
</格式>
<格式>
<名稱>ADPCM</名稱>
<編號>17</編號>
</格式>
<格式>
<名稱>VOX</名稱>
<編號>23</編號>
</格式>
<格式>
<名稱>MP3</名