2011-08-19

[C#]動態設定型態

前言

有個需求,需要從設定檔中取得型態的字串與值,然後在程式中將字串轉換為指定的型態.

如果看文字描述還是不清楚的話,可以看一下下面的範例.

假設xml設定檔中有個如下的設定

<Option Type="System.Int32">88</Option>
<Option Type="System.Drawing.Color">255,255,255</Option>

現在希望程式在執行時將設定轉換為指定的型態.

 

思路

其實我並不常玩reflection,所以對這並不很熟,

不過以這樣的需求,大概要做得的功能如下

1.get object type from string

2.convert type – convert string type to another type

(ps.用英文寫是因為以這樣的字串在google上搜尋比較容易找到可用的資料.)

 

針對第一點,有個

System.Type.GetType("System.Int32");

可以取得type,不過有個問題,如果你要的type不是System下的基礎的struct的話(在Mscorlib.dll裡),

就會回傳null.

像是System.Type.GetType("System.Drawing.Color");就會回傳null.

如果要取得System.Drawing.Color的話,你必須使用完整的assembly-qualified name,如下面這樣的寫法

System.Type.GetType("System.Drawing.Color, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");

(ps.我用的是framework 4.0)

但如果設定檔中要寫Assembly Qualified Name實在是太麻煩了.

所以要換個方式,從現有的assembly中撈type,再轉換.

畢竟要轉換型態也是要有載入該型態的assembly才行

而要取得載入的assembly,可以用下面的語法

Assembly[] AssembliesLoaded = AppDomain.CurrentDomain.GetAssemblies();

然後只要從這裡面撈我們要的type就可以了.到這,第一點也差不多解決了.

 

針對第二點.

有個TypeConvert.ConvertFromString可以處理.

TypeConverter converter = TypeDescriptor.GetConverter(typeOf(System.Int32));
return converter.ConvertFromString(inValue);

 

解決方案

整理一下上面的code就變成下面這個method了.

public static Object TypeConvert(string typeName, string inValue)
{
    Assembly[] AssembliesLoaded = AppDomain.CurrentDomain.GetAssemblies();
    Type trgType = AssembliesLoaded.Select(assembly => assembly.GetType(typeName))
        .Where(type => type != null)
        .FirstOrDefault();
    TypeConverter converter = TypeDescriptor.GetConverter(trgType);
    return converter.ConvertFromString(inValue);
}

ps.上面這個method只是一個簡單的範例,因為還沒有加上一些例外判斷.

還有也需要考慮到如果assembly未載入的話需要有動態載入的機制.

參考網頁

Type.GetType Method (String)
http://msdn.microsoft.com/en-us/library/w3f99sx1.aspx

Show all assemblies loaded by your C# program
http://www.dijksterhuis.org/show-assemblies-loaded-program/

Convert or TryParse from string to T (generic) possible? work around?
http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/d3a139b0-9c14-400d-94f9-440b64a0122a/

How can I get System.Type from "System.Drawing.Color" string
http://stackoverflow.com/questions/944519/how-can-i-get-system-type-from-system-drawing-color-string

Google以後可以查祖譜嗎?

今天看到一篇INDISE的文章 : 比爾蓋茲和賈伯斯,他們的孩子都是 14 歲才能用手機 想說比爾蓋茲不是有點年紀了嗎? 他的小孩應該也都不小了. 他們14歲時應該還沒有甚麼智慧手機吧… 說不定還是在BB call的年代. 所以就好奇的用google查一下有沒...