日期:2014-05-20  浏览次数:20926 次

关于LINQ的匿名类型的使用讨论(欢迎大家进来拍砖)
今天早上看了论坛一位朋友的帖子,是关于C#的匿名类型的,详细请看http://topic.csdn.net/u/20071213/19/45ee97a5-94c1-4895-9849-d6ce6ae21e2a.html
为什么要使用匿名类型?除了方便,我想不出其他的好处。但这种方便是建立在合适的场景下的,当匿名类型不再方便的时候,我们还要执着地使用匿名类型吗?不废话,
我构造一个类似的场景,请看下图:(看不到图片下载附件)

这是大家都熟悉的Northwind数据库里面的2个表。这里,我说明的是匿名类型的重用问题。个人觉得,匿名类型只适合在方法内部“短暂"地使用,如果你
一定要在方法间去重用的话不是不可以,但是那会很麻烦,得不偿失,因为这样匿名类型的方便性被抹杀了。请看下面的代码:
C# code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;
namespace AnonymouseType
{
    class AnonymouseSolve
    {
        //取得ProductID,ProductName,CategoryName
        public IEnumerable GetAnonymousResult()
        {
            NorthwindDataContext db = new NorthwindDataContext();
            var result = db.Products.Select(p => new
            {
                产品ID = p.ProductID,
                产品名称 = p.ProductName,
                类别名称 = p.Category.CategoryName
            });
            return result;
        }
        //取得ProductID,ProductName,CategoryName的前10条记录
        public IEnumerable GetTop10Result(IEnumerable _result)
        {
            var result = _result.Cast<object>();
            var set = result.Select(p => new
            {   //利用反射取得传入的匿名类型的信息
                产品ID = p.GetType().GetProperty("产品ID").GetValue(p, null).ToString(),
                产品名称 = p.GetType().GetProperty("产品名称").GetValue(p, null).ToString(),
                类别名称 = p.GetType().GetProperty("类别名称").GetValue(p, null).ToString()
            }).Take(10);
            return set;
        }
        public IEnumerable GetTop10Result(object IEnumerableOject)
        {
            var result = (IEnumerable)IEnumerableOject;
            return this.GetTop10Result(result);
        }
    }
}


通过上面的代码,可以实现匿名类型在不同的方法间传递,但是,那是我们不得不采取反射为代价的
事实上,新的C#语言构造一个只包含属性的类型如此简单,在这种情况下我们为什么一定要使用匿名类型呢?
C# code

namespace AnonymouseType
{
    class Linker
    {
        public int ProductID
        {
            get;
            set;
        }
        public string ProductName
        {
            set;
            get;
        }
        public string CategoryName
        {
            get;
            set;
        }
    }
}


上面的几句代码就定义了一个程序员可"触摸"的类型,那么查询改成这样岂不更好?
C# code

        public IEnumerable<Linker> GetAnonymousResult()
        {
            NorthwindDataContext db = new NorthwindDataContext();
            var result = db.Products.Select(p => new Linker
            {
               ProductID=p.ProductID,
               ProductName=p.ProductName,
               CategoryName=p.CategoryName
            })
            return result;
        }
      //这里的var实际上是IEnumerable<Linker>
      //该方法的返回值完全适用于任何需要使用linq的场合



所以说,真的需要在取得的数据集中再使用linq,那么,就别用匿名类型了,因为提取匿名类型很麻烦
最后给出测试结果:
代码:
C# code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;
namespace AnonymouseType
{
    class Program
    {
        static void Main(string[] args)
        {
            AnonymouseSolve solve = new AnonymouseSolve();

            foreach (var item in solve.GetTop10Result(solve.GetAnonymousResult()))
            {
                Console.WriteLine("-----------------------------------------");
                Type itemType = item.GetType();
                Console.WriteLine("产品ID:" + itemType.GetProperty("产品ID").GetValue(item, null));
                Console.WriteLine("产品名称:" + itemType.GetProperty("产品名称").GetValue(item, null));
                Console.WriteLine("类别名称:" + itemType.GetProperty("类别名称").GetValue(item, null));
                Console.WriteLine("-----------------------------------------");
                Console.WriteLine();
            }


            var obj = (object)solve.GetAnonymousResult();
            foreach (var item in solve.GetTop10Result(obj))
            {
                Console.WriteLine("-----------------------------------------");
                Type itemType = item.GetType();
                Console.WriteLine("产品ID:" + itemType.GetProperty("产品ID").GetValue(item, null));
                Console.WriteLine("产品名称:" + itemType.GetProperty("产品名称").GetValue(item, null));
                Console.WriteLine("类别名称:" + itemType.GetProperty("类别名称").GetValue(item, null));
                Console.WriteLine("-----------------------------------------");
                Console.WriteLine();
            }

        }
    }
}