我的课程类似于以下内容:
public abstract class Base { }
public class Concrete : Base { }
public class Cement : Base { }
和以下代码
var bases = someEntity.Bases; // returns two Concrete and once Cement
// bases now contains:
// - ProxyBase : Base
// - Concrete : Base
// - Cement : Base
var concretes = bases.OfType<Concrete>();
// concretes only contains one Concrete (i.e. the ProxyBase is ignored)
如何在不使用NHibernate知识污染我的课程的情况下获得两个Concrete
的预期结果?
如果可能的话,我也不想强制映射不使用延迟加载。
答案 0 :(得分:4)
这绝对是动态代理的痛点。您可以将Self属性添加到基类,以便可以获取对未代理对象的引用:
public virtual Base Self
{
get { return this; }
}
然后,您可以通过检查类型来获取特定类型的具体类:
var concretes = bases.Where(b => b.Self is Concrete);
您还可以创建一个扩展方法,以便OfType按预期运行:
public static IEnumerable<T> OfType<T>(this IEnumerable<Base> bases) where T : Base
{
return Enumerable.OfType<T>(bases.Select(b => b.Self));
}
答案 1 :(得分:0)
您必须首先取消它以获取具体类型。
public static T Unproxy<T>(this T obj, ISession session)
{
if (!NHibernateUtil.IsInitialized(obj))
{
NHibernateUtil.Initialize(obj);
}
if (obj is INHibernateProxy)
{
return (T) session.GetSessionImplementation().PersistenceContext.Unproxy(obj);
}
return obj;
}
然后
foreach(var base in bases)
Unproxy<Concrete>(base);
答案 2 :(得分:0)
所以我来临了一个临时解决方案 - 但这很脆弱(如果ToString
被覆盖则会中断,其他ORM可能会以不同的方式工作)并且绝不会令人满意
var concreteTypeName = typeof(Concrete);
// yuck
var concretes = bases.Where(x => String.Equals(x.ToString(), concreteTypeName));
答案 3 :(得分:0)
如果你可以使用INHibernateProxy
试试这个:
var concretes = bases.Where(x => {
var proxy = (INHibernateProxy)x;
return proxy.HibernateLazyInitializer.PersistentClass == typeof(Concrete);
});
或Kirk Woll说:
var concretes = bases.Where(x => x.GetType().BaseType == typeof(Concrete));
答案 4 :(得分:0)
在测试正确的类型时,代理是一种痛苦。 这个answer涵盖了所有不同的解决方案。
no-proxy
延迟加载,这应该可以解决! (explanations)no-proxy
(出于任何原因)的最佳解决方案