J'écris le vérificateur d'autorisation d'accès pour l'entité obtenir à partir de DB. J'ai déclaré la classe de règle de base:NHibernate et l'expression d'exécution
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);
}
Et ceci est aide pour convertir expression> à l'expression>:
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;
}
maintenant, par exemple une règle, pour un article:
public override Expression<Func<Entities.Order, Entities.User, bool>> CanViewExpression
=> (obj, user) => obj.Owner == user;
maintenant j'applique mon expression (enveloppé à la classe de spécification) pour interroger DB. J'extrais toutes les conditions de l'expression (Expression>, Expression>, MethodCallExpression et UnaryExpression) en fonction de ce code https://github.com/rjperes/DevelopmentWithADot.NHibernateSpecifications/blob/master/DevelopmentWithADot.NHibernateSpecifications/SpecificationExtensions.cs
et de l'appliquer à la méthode Query <>.
Je vérifie l'expression des résultats en la compilant à Func et invoque sur chaque élément de la base de données. tout va bien. mais alors j'exécute une requête sur une connexion réelle j'attrape NullReferenceException dans le code de base NHibertante.
après enquête i constaté que exception générée dans la méthode NHibernate.Linq.Visitors.ExpressionKeyVisitor.VisitConstantExpression car _constantToParameterMap est nulle mais utilisé sans aucun contrôle:
protected override Expression VisitConstantExpression(ConstantExpression expression)
{
NamedParameter param;
if (_constantToParameterMap.TryGetValue(expression, out param) && insideSelectClause == false)
nulle a été transmise à partir de NHibernate.Linq.Visitors.WhereJoinDetectors. méthode VisitMemberExpression
var key = ExpressionKeyVisitor.Visit(expression, null);
I utilisé NHibernate 4.1.1
peut tout le mon y aider avec ce problème?
MISE À JOUR 1 c'est une vue de débogage d'expression de résultat:
.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)
}
MISE À JOUR 2 après quelques expériences que j'ai trouvé que l'erreur a eu lieu seulement si j'essaie utilisateur d'accès à l'intérieur de règle ... à savoir si je remplace vérifier avec l'expression, qui ne contient pas l'accès à l'utilisateur tout fonctionne bien. donc le problème est dans l'expression constante, mais je ne peux pas comprendre pourquoi et comment le résoudre
En lisant le titre de la question, je me suis souvenu de "Harry Potter et la pierre du sorcier". Pour de meilleures réponses, pensez à reformuler le titre. –