zoukankan      html  css  js  c++  java
  • 把NHibernate的DomainObject转换为Json!?

         这几天一直在做个Demo,把NHibernate、Ajax.net、WebService 整合在一起。但是到了转换Json的时候就开始郁闷。翻遍了陈先生的第二卷都找不到答案(因为答案在第三卷~)。

         因为Asp.net内置的转Json不能够转换只有Get的属性,而且对象需要默认无参构造函数。在WebService一直报个错误
    如下:

    System.InvalidOperationException: Unable to generate a temporary class (result=1).
    error CS0272: The property or indexer "Test.User.LoginId' cannot be used in this context because the set accessor is inaccessible

        遇到这样的情况就只有两种方法
        1)适用DTO做Json转换。好处是可以直接转换JSON。缺点是,烦,没有用的代码会成培增加,而且翻开理论多多的hibernate in Action,一直告诫DTO是多余的,多余的.......。
        2) 污染DomainObject,全部都有set和get。哈哈,那么在注释上面就要好好地写着“请不要使用本属性的set方法”。而且处理双向关联还是需要人工调整。
        看来两个都是没有好处。
         后来google了一次又一次,看了老赵的blog,介绍怎样用 JavascriptConvter 做转换。试着做一个,还真的运行称成功,虽然无法处理双向关联和index的属性,但是对于我已经很够用啦。
         如果又那位高人想到更好的办法,望不惜赐教。

    下面是我写的代码NHibernate的转换代码。
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Web.Script.Serialization;
    using NHibernate;
    using NHibernate.Burrow;
    using NHibernate.Persister.Entity;
    using NHibernate.Proxy.Poco.Castle;

    namespace TestWeb.Json
    {
        
    public class NHibernateConverter : JavaScriptConverter
        
    {
            
    private const BindingFlags getProperty = BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance;
            
    private const BindingFlags setProperty = BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty;
            
    public Dictionary<Type, string> idBag = new Dictionary<Type, string>();
            
    private IList<Type> supportedTypes;

            
    public NHibernateConverter()
            
    {
            }


            
    public override IEnumerable<Type> SupportedTypes
            
    {
                
    get
                
    {
                    
    if (supportedTypes == null)
                    
    {
                        BurrowFramework bf 
    = new BurrowFramework();
                        ISessionFactory s 
    = bf.GetSession().SessionFactory;

                        supportedTypes 
    = new List<Type>();
                        
    //supportedTypes.Add(typeof(User));
                        IDictionary classf = s.GetAllClassMetadata();
                        
    foreach (Type o in classf.Keys)
                        
    {
                            AbstractEntityPersister cla 
    = (AbstractEntityPersister) classf[o];
                            supportedTypes.Add(o);
                            idBag.Add(o, cla.IdentifierPropertyName);
                        }

                    }

                    
    return supportedTypes;
                }

            }


            
    public override object Deserialize(IDictionary<stringobject> dictionary, Type type,
                                               JavaScriptSerializer serializer)
            
    {
                
    //只是对Public的并且又Set的方法赋值。
                BurrowFramework bf = new BurrowFramework();
                
    object id = dictionary[idBag[type]];

                
    object result = bf.GetSession(type).Get(type, id);

                
    foreach (PropertyInfo info in type.GetProperties(setProperty))
                
    {
                    
    if (dictionary.ContainsKey(info.Name))
                    
    {
                        
    object value = dictionary[info.Name];
                        info.SetValue(result, value, 
    null);
                    }

                }

                
    return result;
            }


            
    public override IDictionary<stringobject> Serialize(object obj, JavaScriptSerializer serializer)
            
    {
                BurrowFramework bf 
    = new BurrowFramework();
                
    //从缓冲中删除。哪么在设定过程中就不会触发LazyLoad。
                bf.GetSession().Evict(obj);
                
    //已经处理过一次的对象。
                ArrayList hadConverObjects = new ArrayList();
                hadConverObjects.Add(obj);

                Dictionary
    <stringobject> result = new Dictionary<stringobject>();
                CreateResult(result, obj, hadConverObjects);
                
    return result;
            }


            
    private void CreateResult(Dictionary<stringobject> result, object obj, IList hadConverObjects)
            
    {
                Type type 
    = obj.GetType();
                
    foreach (PropertyInfo proertyInfo in type.GetProperties(getProperty))
                
    {
                    
    object value;
                    
    //HibernateLazyInitializer是懒加载对象独有属性。
                    if ("HibernateLazyInitializer" != proertyInfo.Name &&
                        GetObject(proertyInfo, obj, hadConverObjects, 
    out value))
                    
    {
                        
    if (!result.ContainsKey(proertyInfo.Name))
                            result.Add(proertyInfo.Name, value);
                    }

                }

            }



            
    private bool GetObject(PropertyInfo propertyInfo, Object obj, IList hadConverObjects, out object value)
            
    {
                PropertyInfo info 
    = obj.GetType().GetProperty("HibernateLazyInitializer");
                value 
    = null;
                
    if (info != null)
                
    {
                    CastleLazyInitializer lazyObject 
    = (CastleLazyInitializer) info.GetValue(obj, null);
                    
    //这个lazyLoad属性并没有初始化。
                    if (lazyObject.IsUninitialized)
                    
    {
                        
    return false;
                    }

                }


                
    if (IsValueType(propertyInfo.PropertyType))
                
    {
                    value 
    = propertyInfo.GetValue(obj, null);
                    
    return true;
                }

                
    else
                
    {
                    value 
    = null;
                    
    //不知道怎样处理Index属性。???
                    if (propertyInfo.GetIndexParameters().Length != 0)
                        
    return false;
                    
                    
    if (supportedTypes.Contains(propertyInfo.PropertyType))
                    
    {
                        value 
    = propertyInfo.GetValue(obj, null);
                        
    //如果已经处理过就不再处理,跳过。
                        if (hadConverObjects.Contains(value))
                            
    return false;
                        
    else
                        
    {
                            hadConverObjects.Add(value);
                            
    return true;
                        }

                    }

                    
    else if (IsCollectionWithNHibernateObject(propertyInfo.PropertyType))
                    
    {
                        value 
    = propertyInfo.GetValue(obj, null);
                        
    return true;
                    }


                    
    return false;
                }

            }


            
    private static bool IsValueType(Type t)
            
    {
                
    if (t == typeof (ValueType) || t == typeof (string))
                    
    return true;
                
    else
                
    {
                    
    if (t.BaseType != null)
                        
    return IsValueType(t.BaseType);
                    
    else return false;
                }

            }


            
    private bool IsCollectionWithNHibernateObject(Type t)
            
    {
                
    if (t == typeof (IEnumerable))
                
    {
                    
    foreach (Type type in t.GetGenericArguments())
                    
    {
                        
    return supportedTypes.Contains(type);
                    }

                    
    return false;
                }

                
    else
                
    {
                    
    if (t.BaseType != null)
                    
    {
                        
    return IsCollectionWithNHibernateObject(t.BaseType);
                    }

                    
    else
                        
    return false;
                }

            }

        }

    }


    最好,按照老赵的方法添加到Web.config就可以了
    老赵的教程:http://www.cnblogs.com/JeffreyZhao/archive/2006/11/13/Inside_Atlas_Series__Web_Services_Access_in_Atlas__Sample_7.html
  • 相关阅读:
    [学习笔记]康托展开
    [模板]平衡树
    [题解]涂色
    [学习笔记]Lucas定理
    欧拉定理及其证明
    一些杂题(排列组合
    swift 动画合集
    UIDynamicAnimator UIKit动力学
    swift 当协议遇见了泛型
    Swift 协议
  • 原文地址:https://www.cnblogs.com/fantasylu/p/1208017.html
Copyright © 2011-2022 走看看