Вы можете создать новый атрибут, который использует существующую PrincipalPermission, если этого будет достаточно для ваших нужд. Если ваша существующая императивная реализация использует PrincipalPermission, то так и должно быть. Однако, если ваша императивная версия делает что-то еще, вам может понадобиться реализовать как пользовательское разрешение, так и соответствующий атрибут. Если вы не уверены, необходимо ли это, возможно, вы могли бы поделиться некоторыми подробностями, касающимися вашего нынешнего императивного подхода ...
После обновления вопроса ...
На самом деле возможно использовать «любую» логику с PrincipalPermission, хотя это требует объединения нескольких экземпляров, что не очень удобно для работы с атрибутом. Это делает более разумным создание пользовательского атрибута, который может выглядеть примерно так:
[Serializable]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public sealed class AnyRolePermissionAttribute : CodeAccessSecurityAttribute
{
public AnyRolePermissionAttribute(SecurityAction action)
: base(action)
{
}
public string Roles { get; set; }
public override IPermission CreatePermission()
{
IList<string> roles = (this.Roles ?? string.Empty).Split(',', ';')
.Select(s => s.Trim())
.Where(s => s.Length > 0)
.Distinct()
.ToList();
IPermission result;
if (roles.Count == 0)
{
result = new PrincipalPermission(null, null, true);
}
else
{
result = new PrincipalPermission(null, roles[0]);
for (int i = 1; i < roles.Count; i++)
{
result = result.Union(new PrincipalPermission(null, roles[i]));
}
}
return result;
}
}
К сожалению, вы не можете использовать массивы в атрибутах безопасности, поэтому список ролей должен быть представлен в виде строки. e.g.:
[AnyRolePermission(SecurityAction.Demand, Roles = "Foo, Bar")]
Вы можете использовать его со своими константами через конкатенацию времени разработки. e.g.:
[AnyRolePermission(SecurityAction.Demand, Roles = Roles.Administrator + ", " + Roles.Editor)]
Что касается вашего настраиваемого поставщика ролей, подходящее место для его использования - в субъекте потока, а не в разрешении или атрибуте. Например, если вы в настоящее время используете GenericPrincipal, вы можете заменить его на пользовательский принципал, который использует ваш пользовательский поставщик ролей для получения ролей целевого удостоверения.