今天.做了個排名顯示的功能. 需要處理並列的情況.. 首先相到了 SQL SERVER2005 的的Rank 函數 ..
後來想是否可以為List<T> 實現一個擴展方法 實現並列排名..
想了想 可以實現 .. 有這個想法就來實現吧..
我的想法是 List<T> 調用Rank方法後 T類型就多了個屬性 用來獲取 名次..
但是怎麼為T類型動態添加屬性 .. 我想到了動態創建一個類型..
.net 可以動態的創建一個類型.. .
有2總方式(我只知道2總...我還想到了個動態構造Lambda 使用new{} 不知道可以麼..我想應該可以. 沒試過(剛剛想到的)))
方式1:使用 System.Reflection.Emit 命名空間下的類.. (都是直接或間接操作IL代碼)
方式2:使用 Microsoft.CSharp; System.CodeDom.Compiler; 這個2個命名空間下的類就可以實現 相 對比較簡單..
我們先來看看 怎麼動態創建一個類型。。
動態創建類型 首先名字要動態的.
這個方法很簡單.. 就是利用ascii碼獲得26個大小寫字母
/// <summary>
/// 動態創建一個英文名稱
/// </summary>
/// <param name="number">長度</param>
/// <returns></returns>
public static string CreateEnglish(int number)
{
Random random = new Random(DateTime.Now.Millisecond);
List<string> en = new List<string>();
Enumerable.Range(97, 26).ToList<int>().ForEach(t => en.Add(((char)t).ToString()));
Enumerable.Range(65, 26).ToList<int>().ForEach(t => en.Add(((char)t).ToString()));
string reuslt = string.Empty;
for (int i = 0; i < number; i++)
{
reuslt += en[random.Next(en.Count)];
}
return reuslt;
}
類型名稱有了 還需要屬性名稱和返回值 .. 就可以動態創建類型類. .屬性和返回值用什麼存放
我首先想到的就是Dictionary<string,string> key 當屬性名稱 value當返回類型..
創建類型還需要導入命名空間. 程序集 所有就就有了下面的這個方法
/// <summary>
/// 動態創建一個類型的實例
/// </summary>
/// <param name="dictionary">屬性名稱和屬性的返回類型的鍵值對(屬性名 稱為Key 返回類型為Value)</param>
/// <param name="referencedAssemblies">需要加載的 dll</param>
/// <returns></returns>
private static Type DynamicCreateType(Dictionary<string, string> dictionary, string[] referencedAssemblies)
{
//指定編譯器的版本
CSharpCodeProvider p = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });
//添加引用
CompilerParameters param = new CompilerParameters (referencedAssemblies);
//創建一個隨機的類名
string className = "__" + CreateEnglish(10);
StringBuilder classCode = new StringBuilder();
//可以考慮繼承 需要主注意 引入 dll 命名空間
classCode.Append("public class ");
classCode.Append(className);
classCode.Append("{");
foreach (var item in dictionary)
{
classCode.Append("public " + item.Value + " " + item.Key + "{ get;set;}");
}
classCode.Append("}");
//編譯
CompilerResults rel = p.CompileAssemblyFromSource(param, classCode.ToString());
//獲得這個類型並返回
return rel.CompiledAssembly.GetType(className);
}
這樣就可以創建一個動態類型了
創建一個動態類型遠遠不夠 還需要為這個動態類型賦值 還要獲得一個類型的說有屬性和返回 值的方法
先寫動態的賦值方法. 動態賦值需要什麼 ? 類型, 屬性名稱和值
/// <summary>
/// 為一個類型實例化並賦值返回
/// </summary>
/// <param name="type">類型</param>
/// <param name="value">屬性名稱和值</param>
/// <returns></returns>
private static object DynamicSetProperty(Type type, Dictionary<string, object> value)
{
//創建類型的實例
object o = type.GetConstructor(Type.EmptyTypes).Invoke(null);
foreach (var item in value)
{
//設置值
o.GetType().GetProperty(item.Key).SetValue(o, item.Value, null);
}
return o;
}
動態的獲取一個類型的屬性和值也類似 只不過是 傳遞對象 返回屬性名稱和值
/// <summary>
/// 獲得一個類型的屬性名稱和值
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static Dictionary<string, object> DynamicGetProperty(object obj)
{
Dictionary<string, object> temp = new Dictionary<string, object>();
//獲得說有公開屬性 並把屬性名稱作為Key 值作為Value
Array.ForEach<PropertyInfo>(obj.GetType().GetProperties(), p => temp.Add(p.Name, p.GetValue(obj, null)));
return temp;
}
動態的創建類型 、設置值、獲取值的方法都有了。 我們還需要什麼方法。。
我們還需要一個獲取一個類型的屬性名稱和返回值的方法
/// <summary>
/// 將一個類型的所有公開的屬性 和返回類型 放入Dictionary內
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
private static Dictionary<string, string> TypeTransform(Type type)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
//獲得說有公開屬性 並把屬性名稱作為Key 值作為Value
Array.ForEach<PropertyInfo>(type.GetProperties(), p => dictionary.Add(p.Name, p.PropertyType.FullName));
return dictionary;
}
這時 動態創建類型 、動態設置值 、動態獲取值 動態獲取屬性和返回值的方法完成了。