把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
原文地址:https://www.cnblogs.com/fantasylu/p/1208017.html