因为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<string, object> 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<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
BurrowFramework bf = new BurrowFramework();
//从缓冲中删除。哪么在设定过程中就不会触发LazyLoad。
bf.GetSession().Evict(obj);
//已经处理过一次的对象。
ArrayList hadConverObjects = new ArrayList();
hadConverObjects.Add(obj);
Dictionary<string, object> result = new Dictionary<string, object>();
CreateResult(result, obj, hadConverObjects);
return result;
}
private void CreateResult(Dictionary<string, object> 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;
}
}
}
}
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<string, object> 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<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
BurrowFramework bf = new BurrowFramework();
//从缓冲中删除。哪么在设定过程中就不会触发LazyLoad。
bf.GetSession().Evict(obj);
//已经处理过一次的对象。
ArrayList hadConverObjects = new ArrayList();
hadConverObjects.Add(obj);
Dictionary<string, object> result = new Dictionary<string, object>();
CreateResult(result, obj, hadConverObjects);
return result;
}
private void CreateResult(Dictionary<string, object> 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