假设我的用户标记为延迟加载:
public class User
{
public int UserId { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
如果我以这种方式获得用户,我知道标签未加载:
User myUser;
using (var context = new MyContext())
{
myUser = context.Users.Find(4);
}
如何在Tags
子句之外测试using
集合存在?
if (myUser.Tags == null) // throws an ObjectDisposedException
我可以使用try / catch但必须有更好的方法。
答案 0 :(得分:2)
我能想到的唯一方法是能够在类属性getter中执行非虚拟调用(类似于在派生类中执行base.Something
时)。由于没有办法用纯C#或反射来做到这一点,我最终得到了以下帮助方法,该方法利用System.Reflection.Emit
LCG(轻量级代码生成)发出Call
IL指令而不是正常Callvirt
:
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
public static class Utils
{
public static TValue GetClassValue<TSource, TValue>(this TSource source, Expression<Func<TSource, TValue>> selector)
where TSource : class
{
Func<TSource, TValue> getValue = null;
if (source.GetType() != typeof(TSource))
{
var propertyAccessor = selector.Body as MemberExpression;
if (propertyAccessor != null)
{
var propertyInfo = propertyAccessor.Member as PropertyInfo;
if (propertyInfo != null)
{
var getMethod = propertyInfo.GetGetMethod();
if (getMethod != null && getMethod.IsVirtual)
{
var dynamicMethod = new DynamicMethod("", typeof(TValue), new[] { typeof(TSource) }, typeof(Utils), true);
var il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, getMethod, null);
il.Emit(OpCodes.Ret);
getValue = (Func<TSource, TValue>)dynamicMethod.CreateDelegate(typeof(Func<TSource, TValue>));
}
}
}
}
if (getValue == null)
getValue = selector.Compile();
return getValue(source);
}
}
它可以用于单一和集合类型的导航属性,如下所示:
if (myUser.GetClassValue(x => x.Tags) == null)
答案 1 :(得分:0)
使用天真的try / catch的另一个解决方案,与其他答案相比,不确定性能:
if (myUser.IsCollectionLoaded(x => x.Tags))
用法:
EXEC PROC_A @p_para = 'Test'