博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

为List添加排序的函数 处理并列排名情况(上篇)

Posted on 2009-05-21 10:47  陈 亮  阅读(2318)  评论(6编辑  收藏  举报

今天.做了个排名显示的功能.  需要处理并列的情况.. 首先相到了 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(
9726).ToList<int>().ForEach(t => en.Add(((char)t).ToString()));
            Enumerable.Range(
6526).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<stringstring> dictionary, string[] referencedAssemblies)
        {
            
//指定编译器的版本
            CSharpCodeProvider p = new CSharpCodeProvider(new Dictionary<stringstring>() { { "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<stringobject> 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<stringobject> DynamicGetProperty(object obj)
        {
            Dictionary
<stringobject> temp = new Dictionary<stringobject>();
            
//获得说有公开属性 并把属性名称作为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<stringstring> TypeTransform(Type type)
        {
            Dictionary
<stringstring> dictionary = new Dictionary<stringstring>();
            
//获得说有公开属性 并把属性名称作为Key  值作为Value
            Array.ForEach<PropertyInfo>(type.GetProperties(), p => dictionary.Add(p.Name, p.PropertyType.FullName));
            
return dictionary;
        }

这时  动态创建类型  、动态设置值 、动态获取值  动态获取属性和返回值的方法完成了。

 如何实现及其使用。 请看下篇