我为从db获取的实体写入访问权限检查器。 我宣布基地规则类:NHibernate和运行时表达式
abstract class AccessRule
{
private Func<object, Entities.User, bool> _canViewCompiledExpression;
public abstract Expression<Func<object, Entities.User, bool>> RawCanEditExpression { get; }
public abstract Type ObjectType { get; }
public Expression<Func<object, bool>> CreateCanViewExpression(AccessContext accessContext, Entities.User user)
{
var entityArgument = Expression.Parameter(typeof(object), "arg1");
var userExpression = Expression.Constant(user, typeof(Entities.User));
var body = Expression.Invoke(RawCanViewExpression, entityArgument, userExpression);
return (Expression<Func<object, bool>>)Expression.Lambda(body, entityArgument);
}
}
abstract class AccessRule<T> : AccessRule
where T : Entity
{
public override Type ObjectType => typeof(T);
public abstract Expression<Func<T, Entities.User, bool>> CanViewExpression { get; }
public override Expression<Func<object, Entities.User, bool>> RawCanViewExpression => ExpressionHelper.BoxExpression(CanViewExpression);
}
这是把表达式帮手>表达式>:
public static Expression<Func<object, Entities.User, bool>> BoxExpression<T>(Expression<Func<T, Entities.User, bool>> expression)
{
var objParameter = Expression.Parameter(typeof(object), "arg1");
var userParameter = Expression.Parameter(typeof(Entities.User), "arg2");
var convertExpression = Expression.Convert(objParameter, typeof(T));
var body = Expression.Invoke(expression, convertExpression, userParameter);
var result = Expression.Lambda<Func<object, Entities.User, bool>>(body, objParameter, userParameter);
return result;
}
现在,例如一个规则,一个项目:
public override Expression<Func<Entities.Order, Entities.User, bool>> CanViewExpression
=> (obj, user) => obj.Owner == user;
现在我应用我的表达式(包装到规范类)查询到数据库。我基于此代码从表达式(如Expression>,Expression>,MethodCallExpression和UnaryExpression)中提取所有条件,并将其应用于查询<>方法https://github.com/rjperes/DevelopmentWithADot.NHibernateSpecifications/blob/master/DevelopmentWithADot.NHibernateSpecifications/SpecificationExtensions.cs
>
我检查结果表达式编译为Func并调用数据库上的每个项目。一切都好。 但后来我执行查询真正的连接,我在NHibertante核心代码捕获NullReferenceException。
调查后,我发现在NHibernate.Linq.Visitors.ExpressionKeyVisitor.VisitConstantExpression方法产生的异常,因为_constantToParameterMap为空,但没有任何检查使用:
protected override Expression VisitConstantExpression(ConstantExpression expression)
{
NamedParameter param;
if (_constantToParameterMap.TryGetValue(expression, out param) && insideSelectClause == false)
空从NHibernate.Linq.Visitors.WhereJoinDetectors通过。 VisitMemberExpression方法
var key = ExpressionKeyVisitor.Visit(expression, null);
我使用的NHibernate 4.1.1
可以anybod Ÿ帮助解决这个问题?
更新1 这是结果表达式的调试视图:
.Lambda #Lambda1<System.Func`2[System.Object,System.Boolean]>(System.Object $arg1) {
.Invoke (.Lambda #Lambda2<System.Func`3[System.Object,Project.Entities.User,System.Boolean]>)(
$arg1,
.Constant<Project.Entities.User>(Project.Entities.User))
}
.Lambda #Lambda2<System.Func`3[System.Object,Project.Entities.User,System.Boolean]>(
System.Object $arg1,
Project.Entities.User $arg2) {
.Invoke (.Lambda #Lambda3<System.Func`3[Project.Entities.Order,Project.Entities.User,System.Boolean]>)(
(Project.Entities.Windfarm)$arg1,
$arg2)
}
.Lambda #Lambda3<System.Func`3[Project.Entities.Order,Project.Entities.User,System.Boolean]>(
Portal.Domain.Entities.Windfarm $obj,
Portal.Domain.Entities.User $user) {
.Call($obj.Owner).Equeal($user)
}
更新2 经过一些实验,我发现只有当我尝试内部规则接入用户......也就是说,如果发生错误我用表达式替换检查,其中不包含对用户的访问所有工作正常。所以问题是在不断的表达,但我不明白为什么以及如何解决它
读题的题目,我想起了“哈利波特与魔法石”。为了获得更好的答复,请考虑重新改写标题。 –