zoukankan      html  css  js  c++  java
  • 没有实体,不写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,
                      
    nullnew 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<stringobject>();
                    
    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 包里的类,字符串读出来之后,双引号没有去掉,烦人  :( 。)







  • 相关阅读:
    使用Micrisoft.net设计方案 第三章Web表示模式 Web模式集群详细介绍 Page Cache(页面缓存)
    使用Micrisoft.net设计方案 第三章Web表示模式 Web模式集群详细介绍 Intercepting Filter(截取筛选器)
    使用Micrisoft.net设计方案 第三章Web表示模式 Web模式集群详细介绍
    使用Micrisoft.net设计方案 第三章Web表示模式
    使用Micrisoft.net设计方案 第二章组织模式
    使用Micrisoft.net设计方案 第一章 企业解决方案中构建设计模式
    Area区域路由的配置
    Area路由的配置
    layUI+mvc动态菜单数据表
    layUI+mvc动态菜单控制器
  • 原文地址:https://www.cnblogs.com/cloudbeer/p/1540917.html
Copyright © 2011-2022 走看看