Поскольку вы можете использовать только константы, типы или инициализаторы массивов в параметрах атрибутов, они, вероятно, не подойдут или, по крайней мере, не будут такими гибкими.
В качестве альтернативы, вы можете использовать нечто подобное.придумал при решении этой проблемы.
Это API:
public static class SecurityGuard
{
private const string ExceptionText = "Permission denied.";
public static bool Require(Action<ISecurityExpression> action)
{
var expression = new SecurityExpressionBuilder();
action.Invoke(expression);
return expression.Eval();
}
public static bool RequireOne(Action<ISecurityExpression> action)
{
var expression = new SecurityExpressionBuilder();
action.Invoke(expression);
return expression.EvalAny();
}
public static void ExcpetionIf(Action<ISecurityExpression> action)
{
var expression = new SecurityExpressionBuilder();
action.Invoke(expression);
if(expression.Eval())
{
throw new SecurityException(ExceptionText);
}
}
}
public interface ISecurityExpression
{
ISecurityExpression UserWorksForCompany(string company);
ISecurityExpression IsTrue(bool expression);
}
Затем создайте построитель выражений:
public class SecurityExpressionBuilder : ISecurityExpression
{
private readonly List<SecurityExpression> _expressions;
public SecurityExpressionBuilder()
{
_expressions = new List<SecurityExpression>();
}
public ISecurityExpression UserWorksForCompany(string company)
{
var expression = new CompanySecurityExpression(company);
_expressions.Add(expression);
return this;
}
public ISecurityExpression IsTrue(bool expr)
{
var expression = new BooleanSecurityExpression(expr);
_expressions.Add(expression);
return this;
}
public bool Eval()
{
return _expressions.All(e => e.Eval());
}
public bool EvalAny()
{
return _expressions.Any(e => e.Eval());
}
}
Реализуйте выражения безопасности:
internal abstract class SecurityExpression
{
public abstract bool Eval();
}
internal class BooleanSecurityExpression : SecurityExpression
{
private readonly bool _result;
public BooleanSecurityExpression(bool expression)
{
_result = expression;
}
public override bool Eval()
{
return _result;
}
}
internal class CompanySecurityExpression : SecurityExpression
{
private readonly string _company;
public CompanySecurityExpression(string company)
{
_company = company;
}
public override bool Eval()
{
return (WhereverYouGetUser).Company == company;
}
}
Вы можете добавить столько пользовательских выражений, сколько вам нужно.Инфраструктура немного сложна, но тогда ее использование действительно простое:
public ActionResult AcmeOnlyAction()
{
SecurityGuard.ExceptionIf(s => s.UserWorksForCompany("Acme"));
}
Вы также можете связать выражение и использовать его в качестве условия в примере (используя SecurityGuard.Require()
).
Прошу прощения за длинный пост, надеюсь, это поможет.