没有实体,不写Converter,在 Silverlight 中给 DataGrid 绑定数据


给 DataGrid 绑定数据的通常做法是:

1、服务器端将数据集合 序列化 成 XML,或者其它格式。
2、在Silverlight 中获取到数据,并反序列化成实体集合。
3、绑定到 DataGrid ,搞定。


象RIA Service 也是类似的做法。只是 VS 将实体自动帮创建好了。


并且,DataGrid 不支持匿名类集合,使用匿名集合,需要自己写 Converter 才能绑定。否则只能绑定出 Title 和 数量。 :D


然后,我的想法是:
获取集合数据,在内存中动态构造出实体,赋值,然后绑定。

 

http://www.simple-talk.com/dotnet/.net-framework/dynamically-generating--typed-objects-in-.net/ 这里:

有一个类:
DataSourceCreator 可以干这件事情。上面的那个网址可以下载到这个类。


源代码如下: 


    
public   static   class  DataSourceCreator
    {
        
private   static   readonly  Regex PropertNameRegex  =
                
new  Regex( @" ^[A-Za-z]+[A-Za-z0-9_]*$ " , RegexOptions.Singleline);

        
private   static   readonly  Dictionary < string , Type >  _typeBySigniture  =
                
new  Dictionary < string , Type > ();


        
public   static  IEnumerable ToDataSource( this  IEnumerable < IDictionary >  list)
        {
            IDictionary firstDict 
=   null ;
            
bool  hasData  =   false ;
            
foreach  (IDictionary currentDict  in  list)
            {
                hasData 
=   true ;
                firstDict 
=  currentDict;
                
break ;
            }
            
if  ( ! hasData)
            {
                
return   new   object [] { };
            }
            
if  (firstDict  ==   null )
            {
                
throw   new  ArgumentException( " IDictionary entry cannot be null " );
            }

            
string  typeSigniture  =  GetTypeSigniture(firstDict);

            Type objectType 
=  GetTypeByTypeSigniture(typeSigniture);

            
if  (objectType  ==   null )
            {
                TypeBuilder tb 
=  GetTypeBuilder(typeSigniture);

                ConstructorBuilder constructor 
=
                            tb.DefineDefaultConstructor(
                                        MethodAttributes.Public 
|
                                        MethodAttributes.SpecialName 
|
                                        MethodAttributes.RTSpecialName);


                
foreach  (DictionaryEntry pair  in  firstDict)
                {
                    
if  (PropertNameRegex.IsMatch(Convert.ToString(pair.Key),  0 ))
                    {
                        CreateProperty(tb,
                                        Convert.ToString(pair.Key),
                                        GetValueType(pair.Value));
                    }
                    
else
                    {
                        
throw   new  ArgumentException(
                                    
@" Each key of IDictionary must be 
                                alphanumeric and start with character.
" );
                    }
                }
                objectType 
=  tb.CreateType();

                _typeBySigniture.Add(typeSigniture, objectType);
            }

            
return  GenerateEnumerable(objectType, list, firstDict);
        }

        
private   static  Type GetTypeByTypeSigniture( string  typeSigniture)
        {
            Type type;
            
return  _typeBySigniture.TryGetValue(typeSigniture,  out  type)  ?  type :  null ;
        }

        
private   static  Type GetValueType( object  value)
        {
            
return  value  ==   null   ?   typeof ( object ) : value.GetType();
        }

        
private   static   string  GetTypeSigniture(IDictionary firstDict)
        {
            StringBuilder sb 
=   new  StringBuilder();
            
foreach  (DictionaryEntry pair  in  firstDict)
            {
                sb.AppendFormat(
" _{0}_{1} " , pair.Key, GetValueType(pair.Value));
            }
            
return  sb.ToString().GetHashCode().ToString().Replace( " - " " Minus " );
        }

        
private   static  IEnumerable GenerateEnumerable(
                 Type objectType, IEnumerable
< IDictionary >  list, IDictionary firstDict)
        {
            var listType 
=   typeof (List <> ).MakeGenericType( new [] { objectType });
            var listOfCustom 
=  Activator.CreateInstance(listType);

            
foreach  (var currentDict  in  list)
            {
                
if  (currentDict  ==   null )
                {
                    
throw   new  ArgumentException( " IDictionary entry cannot be null " );
                }
                var row 
=  Activator.CreateInstance(objectType);
                
foreach  (DictionaryEntry pair  in  firstDict)
                {
                    
if  (currentDict.Contains(pair.Key))
                    {
                        PropertyInfo property 
=
                            objectType.GetProperty(Convert.ToString(pair.Key));
                        property.SetValue(
                            row,
                            Convert.ChangeType(
                                    currentDict[pair.Key],
                                    property.PropertyType,
                                    
null ),
                            
null );
                    }
                }
                listType.GetMethod(
" Add " ).Invoke(listOfCustom,  new [] { row });
            }
            
return  listOfCustom  as  IEnumerable;
        }

        
private   static  TypeBuilder GetTypeBuilder( string  typeSigniture)
        {
            AssemblyName an 
=   new  AssemblyName( " TempAssembly "   +  typeSigniture);
            AssemblyBuilder assemblyBuilder 
=
                AppDomain.CurrentDomain.DefineDynamicAssembly(
                    an, AssemblyBuilderAccess.Run);
            ModuleBuilder moduleBuilder 
=  assemblyBuilder.DefineDynamicModule( " MainModule " );

            TypeBuilder tb 
=  moduleBuilder.DefineType( " TempType "   +  typeSigniture
                                , TypeAttributes.Public 
|
                                TypeAttributes.Class 
|
                                TypeAttributes.AutoClass 
|
                                TypeAttributes.AnsiClass 
|
                                TypeAttributes.BeforeFieldInit 
|
                                TypeAttributes.AutoLayout
                                , 
typeof ( object ));
            
return  tb;
        }

        
private   static   void  CreateProperty(
                        TypeBuilder tb, 
string  propertyName, Type propertyType)
        {
            FieldBuilder fieldBuilder 
=  tb.DefineField( " _ "   +  propertyName,
                                                        propertyType,
                                                        FieldAttributes.Private);


            PropertyBuilder propertyBuilder 
=
                tb.DefineProperty(
                    propertyName, PropertyAttributes.HasDefault, propertyType, 
null );
            MethodBuilder getPropMthdBldr 
=
                tb.DefineMethod(
" get_ "   +  propertyName,
                    MethodAttributes.Public 
|
                    MethodAttributes.SpecialName 
|
                    MethodAttributes.HideBySig,
                    propertyType, Type.EmptyTypes);

            ILGenerator getIL 
=  getPropMthdBldr.GetILGenerator();

            getIL.Emit(OpCodes.Ldarg_0);
            getIL.Emit(OpCodes.Ldfld, fieldBuilder);
            getIL.Emit(OpCodes.Ret);

            MethodBuilder setPropMthdBldr 
=
                tb.DefineMethod(
" set_ "   +  propertyName,
                  MethodAttributes.Public 
|
                  MethodAttributes.SpecialName 
|
                  MethodAttributes.HideBySig,
                  
null new  Type[] { propertyType });

            ILGenerator setIL 
=  setPropMthdBldr.GetILGenerator();

            setIL.Emit(OpCodes.Ldarg_0);
            setIL.Emit(OpCodes.Ldarg_1);
            setIL.Emit(OpCodes.Stfld, fieldBuilder);
            setIL.Emit(OpCodes.Ret);

            propertyBuilder.SetGetMethod(getPropMthdBldr);
            propertyBuilder.SetSetMethod(setPropMthdBldr);
        }
    }

直接拷贝这code,需要加入以下引用:

using System.Text.RegularExpressions;
using System.Collections;
using System.Reflection;
using System.Text;
using System.Reflection.Emit;

 


这个类的静态方法 ToDataSource 扩展了 IEnumerable 接口,将普通的 IDictionary 集合 转化成了实体集合。


好。现在来看 json。


将 json 转化为 IDictionary 应该不是一件难事,通过试验,代码如下:


    
public   partial   class  MainPage : UserControl
    {
        
private  ProductContext _pro  =   new  ProductContext();
        
public  MainPage()
        {
            InitializeComponent();

            
string  jsonData  =   @"
[
   {
      ""TitleID"":1,
      ""Title"":""CEO""
   }, 
   {
      ""TitleID"":2,
      ""Title"":""CTO""
   }, 
   {
      ""TitleID"":3,
      ""Title"":""CXO""
   }, 
   {
      ""TitleID"":4,
      ""Title"":""数据库管理员1221""
   }
]
" ;



            System.Json.JsonArray data 
=  System.Json.JsonArray.Parse(jsonData)  as  System.Json.JsonArray;

            grid.ItemsSource 
=  GenerateData(data).ToDataSource();

            
        }


        
public  IEnumerable < System.Collections.IDictionary >  GenerateData(System.Json.JsonArray data)
        { 
            
foreach  (System.Json.JsonObject jo  in  data)
            {
                var dict 
=   new  Dictionary < string object > ();
                
foreach  ( string  key  in  jo.Keys)
                {
                    dict.Add(key, jo[key]);
                }

                
yield   return  dict;
            }

        }

    }



现在,我们可以使用同一个 Controller 驱动 silverlight 或者 ext 啦。

btw: 使用 System.Web.Script.Serialization.JavaScriptSerializer 可以序列化出 json, 这个类在 System.Web.Extensions 包里。

(M$的人真不小心,使用 System.Json 包里的类,字符串读出来之后,双引号没有去掉,烦人  :( 。)







转载于:https://www.cnblogs.com/cloudbeer/archive/2009/08/07/1540917.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值