1 緣起
老趙在談表達式樹的緩存(2):由表達式樹生成字符串 中提到,在描述Type信息時討論FullName或者AssemblyQualifiedName提供完整的Type信息,雖是小話題,但卻是值得有聊的話題。在.NET中反應一個Type名稱信息的有以下三個屬性,分別是:
Name,獲取當前成員的名稱。
FullName,獲取Type 的完全限定名,包括Type的命名空間,但不包括程序集。
AssemblyQualifiedName,獲取Type的程序集限定名,其中包括從中加載Type 的程序集的名稱。事實上,AssemblyQualifiedName被定義為只讀abstract屬性,具體的實現由其派生類來實現,例如TypeBuilder,我們可以根據其具體實現類型對此有個大致的了解。
此處的定義毋庸置疑是官方的(MSDN),俗話說,事實是檢驗真理的唯一標准,那麼這三個相近的概念,究竟代表了怎樣的不同,我們回到事實近看分曉。
2 暢聊Name
2.1 由簡單的開始
由簡單開始,我們不妨看看object的三個不同Name返回的事實真相:
static void Main(string[] args)
{
Type t1 = typeof(object);
Console.WriteLine(t1.Name);
Console.WriteLine(t1.FullName);
Console.WriteLine(t1.AssemblyQualifiedName);
}
執行結果呢?
誠如MSDN所說,Name返回了簡單的類型名稱,FullName包含命名空間,而AssemblyQualifiedName則包含程序集全名稱。而對於非強名稱程序集,其AssemblyQualifiedName依然返回,相關的程序集信息,例如:
Console.WriteLine(t3.AssemblyQualifiedName);
Anytao.Learning.ExpressionTree.One, Anytao.Learning.ExpressionTree, Version=1.0.
0.0, Culture=neutral, PublicKeyToken=null
2.2 向復雜過度
如果我們只把目光停留在簡單類型,那麼這三個家伙也不值得花點小時間來注意了,除了簡單,還得復雜。所以,我饒尤其是的把Expression拿來抓丁了:
static void Main(string[] args)
{
Type t2 = typeof(Expression<Func<int, int>>);
Console.WriteLine(t2.Name);
Console.WriteLine(t2.FullName);
Console.WriteLine(t2.AssemblyQualifiedName);
}
執行的結果呢?
顯然,對於答案,引起我們關注的是在Expression<Func<int, int>>中,其FullName的Func<int, int>類型,以及int類型均獲取到其AssemblyQualifiedName,而不是FulName。這留給我們一個大大的疑問,對其原因進行一點點深究,我們就可以有這樣的思考,Func<T>以及int分別存在於System.Core和mscorlib程序集,對於我們本身程序集而言,完全有可能在其他引用程序集中引入一個FullName相同的Assembly,所以為唯一限定起見,以AssemblyQualifiedName標示Func<T>和int是完全正確的。
同意的問題,存在於List<T>等其他類型。任何可替換類型參數的實際類型,都可能由不同程序集的加載而變得不夠“唯一”,所以AssemblyQualifiedName來限定List<T>的FullName是明智的。
2.3 順便看看Type.ToString()
Type類型還有一個ToString(),用於返回Type的Name,那麼這個Name究竟是這三個中的哪一個呢?如果看了答案,你肯定又一次崩潰:
static void Main(string[] args)
{
Type t1 = typeof(object);
Type t2 = typeof(Expression<Func<int, int>>);
Type t3 = typeof(One);
Type t4 = typeof(List<int>);
Console.WriteLine(t1.ToString());
Console.WriteLine(t2.ToString());
Console.WriteLine(t3.ToString());
Console.WriteLine(t4.ToString());
}
我們看看此時的結果:
雖然很無語,Type.ToString()事實上並未返回Name、FullName或者AssemblyQualifiedName,而是不完全的FullName,具體就不做過多陳述了,我們可以由結果看得很明白。
3 回到問題
顯然,FullName在一個程序集中是唯一限定的,包含了所在的命名空間,而AssemblyQualifiedName則更包含其程序集名稱,對於復雜類型的例如List<T>這樣的類型,即便是FullName也將以AssemblyQualifiedName顯示其類型參數,所以對於老趙的方案FullName是完全可以勝任為不同Type實現唯一key值的需求。
你認為呢?
文章來源:http://anytao.cnblogs.com/