Sorry. It's a general problem. I need to easily create custom collection usable with nhibernate. At the beginning, I gave an example with a collection that inherits List<T>, but now I have a problem with a collection that hinerits Dictionary<T, U>.
I tried to write a IPropertyAccessor implementation :
public class DefaultAccessor : IPropertyAccessor
{
#region IPropertyAccessor Members
public IGetter GetGetter(System.Type theClass, string propertyName)
{
return new Getter(GetField(propertyName, theClass));
}
public ISetter GetSetter(System.Type theClass, string propertyName)
{
return new Setter(GetField(propertyName, theClass));
}
private FieldInfo GetField(string propertyName, System.Type theClass)
{
string fieldName = new HiddenFieldStrategy().GetFieldName(propertyName);
if(fieldName == null)
fieldName = new PascalCaseUnderscoreStrategy().GetFieldName(propertyName);
FieldInfo field = GetFieldInternal(theClass, fieldName);
if (field == null) throw new PropertyNotFoundException(theClass, fieldName);
return field;
}
private static FieldInfo GetFieldInternal(System.Type type, string fieldName)
{
if (type == null || type == typeof(object)) return null;
FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
return (field != null) ? field : GetFieldInternal(type.BaseType, fieldName);
}
#endregion
private class Setter : ISetter
{
private FieldInfo fieldInfo;
internal Setter(FieldInfo fieldInfo)
{
this.fieldInfo = fieldInfo;
}
public void Set(object target, object value)
{
fieldInfo.SetValue(target, Activator.CreateInstance(fieldInfo.FieldType,new IDictionaryToGenericIDictionaryAdaptator<Iso, string>((IDictionary)value)));
}
public string PropertyName
{
get { return null; }
}
public MethodInfo Method
{
get { return null; }
}
}
private class Getter : IGetter
{
private FieldInfo fieldInfo;
private System.Type returnType;
public Getter(FieldInfo fieldInfo)
{
this.fieldInfo = fieldInfo;
returnType = GetReturnType(fieldInfo);
}
public object Get(object target)
{
var obj = fieldInfo.GetValue(target);
if (obj == null) return null;
return new Dictionary<Iso, string>((IDictionary<Iso, string>)obj);
}
public System.Type ReturnType
{
get { return returnType; }
}
public string PropertyName
{
get { return null; }
}
public MethodInfo Method
{
get { return null; }
}
private static System.Type GetReturnType(FieldInfo field)
{
System.Type type = field.FieldType;
// pretend that it is still a collection, otherwise lazy initialization stuff won't work
if (type.IsGenericType && typeof(ICollection<>).IsAssignableFrom(type.GetGenericTypeDefinition()))
return typeof(ICollection<>).MakeGenericType(type.GetGenericArguments());
return type;
}
}
}
The data are loaded without problem in my objects. However, it doesn't succeed on commit(). I get the following error :
could not insert collection: [TestNhibernate.Test.Name#1]
Inner exception : {"Specified cast is not valid."}
Message : "could not insert collection: [TestNhibernate.Test.Name#1]"
Do you know what is the problem ? I don't insist on doing this way, I just want an easy solution to implement custom collections with nhibernate.
|