Convert anonymous type into any type

Introduction    

This article describes how to handle conversion from anonymous type to a specific type by using .NET 3.5 extensions.
Especially it is helpful when using LINQ to SQL to retrieve data in forms of Lists and/or Arrays.  

Problem

 

With Microsoft LINQ to SQL you enjoy the ability of using strong programming language and at the same time having control over your data.
Data objects are represented by classes automatically created when you link your data structure to your visual studio project via dbml files.

Instead of dividing your attention between SQL and programming you can now write data retrieving procedures within your  Visual Studio programming environment.

At the same time LINK to SQL sometimes creates some challenges.
One of such is the Anonymous type that is returned by LINQ to SQL queries.


When you join several data base tables in one query you have to choose how to organize the returning sequence.
Often enough you have to create sequence that returns a list or an array of Anonymous type objects.

Many programmers, myself including, think that it is not best practice to operate with such anonymous type objects at business and/or UI layers.

Solution 

Let's have a database which consists of 2 tables: Client and Order.

The Client table has client specific information. In our case it is Name and AddressID, which obviously points to some depository with addresses info for this client, but it, is not our concern now.
The Order table has some text describing an order in string format and ClientID column, which points to an ID of the client  who made the Order.

Say we want to get all clients info and also how many orders each client made.

Let's see the data by running the following queries:

The group by last query returns the set of rows having ID, Name, Address ID, and Total Orders for all clients from Client table.
In old days you would use ADO.NET to retrieve and work with the data.

Addressing the problem   

 If you want to use LINQ to SQL you would  create a procedure to retrieve the sequence with required info:

In this procedure we joined Client and Order tables and grouped by Client, calculating how many orders the client made.
Result is returned in the following format:
ID, Address ID, Name, and Total Orders.

Let us add a property into the Client class using the ability to create partial class and add any property/methods we want to the classess generated by Visual Studio auto designer:

public int TotalOrders { get; set; }

Now the Client class has: ID, Name, AddressID, TotalOrders properties.

A list of objects with all these properties are returned by LINQ to SQL GetClientsWithTotalOrders() procedures.

But if you try to compile the procedure you will get the error:

Error    1    Cannot convert type 'System.Collections.Generic.List<AnonymousType#1>' to 'System.Collections.Generic.List<CodeProject.LinkToSql.Client>'    C:/Development/VS2008/Projects/CodeProject/CodeProject/LinkToSql/DbHandlers.cs    38    23    CodeProject


Unfortunately there is no way the compiler would recognize that the anonymous type created by the program has the same set of properties that you Client class.

That means that you will have to deal with anonumous type List after you retrieve the data.

How can we convert this anonymous type into the Client type?

By writing extensions to deal with anonymus types objects.

I created 2 extensions to handle this:

This extensions allows to convert an object of anonimous type into the specified type.

If you have an object of an anonymous type and want to covert it to Client type you need to call this extension:

object obj=getSomeObjectOfAnonymoustype();
Client client=obj.ToType(typeof (Client));


Let see how it works:

At first it creates an empty temporary object of Client type using Activator.CreateInstance() procedure.

Then it loops through every property info of calling object, gets its value and re-assigns the value or corresponding property of the newly created Client object.

Finally it returns the object of Client type having all the properties populated from the calling object.


So for a single object the problem is solved.


What about List of such objects? Or Arrays?

The second extension I created is to transform a List of Anonymous type objects into the List of a specific type objects

The first row  of the above code is rather interesting:

When we call  MakeGenericType(t) function on typeof(List<>) it substitutes type of List objects  with the type T and  returns a Type object representing the List of T objects.

After that everything is very straight forward:

The Activator creates an empty list of T objects.

l.GetType().GetMethod("Add") returns MethodInfo object which we will use  to call  method Add() of  the  newly created list.

Then we are looping through  the original list, changing original type of each element into T type by calling our own extension ToType<T>(), and finally adding this item into the list of T type.

The returned result is the list of T type.

Let us update the procedure with this new extension:

Calling ToNonAnonymousList(typeof(Client)) converts List of anonymous type to  List of Client type .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值