私はまったく同じことに取り組んでおり、カスタム[Attributes]
でこれを行うことは完全に可能だと思います。ここで私は、動的選択-文でそれをやったかの小さな実装です:
はまず、私は、入力として列挙UserRolesを取るカスタム属性を持っている:
[AttributeUsage(AttributeTargets.Property)]
public class RestrictUserRoles : Attribute
{
public RestrictUserRoles(UserRoles roles)
{
Roles = roles;
}
public UserRoles Roles { get; }
}
UserRoles、列挙型を実装することができます
[Flags]
public enum UserRoles
{
[Description("Administrator")]
Admin = 1,
[Description("Employee")]
Employee = 2,
[Description("Head of a division")]
DivisionHead = 4,
[Description("Fired")]
Fired = 8
}
一部の従業員は管理者、部門ヘッド(さらには解雇された人)になる可能性があるため、列挙型を使用します。
次に、IQueryable拡張機能を使用して、ユーザーが表示する権限を持つすべてのプロパティを取得し、選択したプロパティとそれらのプロパティを交差させます。これを行うには、動的なLinqとリフレクションを使用します。
public static class QueryableExtensions
{
public static IQueryable SelectProperties<T>(this IQueryable<T> source, UserRoles roles, string criteria)
{
// get all the properties that a user is authorized to see
var authenticatedProperties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(prop => prop.CustomAttributes.Any(attr =>
attr.AttributeType == typeof(RestrictUserRoles) &&
(((RestrictUserRoles) Attribute.GetCustomAttribute(prop, typeof(RestrictUserRoles))).Roles & roles) !=
0))
.Select(prop => prop.Name)
.ToList();
// if there aren't any, then the user is not
// authorized to view any properties
// DISCLAIMER: or someone has forgotten to mark any properties
// with the RestrictUserRoles-attribute
if (!authenticatedProperties.Any()) throw new UnauthorizedAccessException();
// we get all the properties that the user wants to
// select from the string that was passed to the function in
// the form Prop1, Prop2, Prop3
var selectProperties = criteria
.Split(',')
.Select(property => property.Trim());
// Get the intersection between these properties, IE we
// select only those properties that the user has selected
// AND is authorized to view
var properties = authenticatedProperties
.Intersect(selectProperties)
.ToList();
// if there are none that intersect, return all those
// properties that a user is authorized to view
if (!properties.Any()) properties = authenticatedProperties;
// run the query using dynamic linq
return source.Select("new(" + properties.JoinToString(",") + ")");
}
}
これはフィールドテストではありませんが、それはトリックを行う必要がありますし、変異にも容易に拡張可能です。
編集:私は、私は以下の定義すべてのプロパティを結合するために拡張機能を使用することを忘れていました:
public static string JoinToString(this IEnumerable<string> list, string delimiter = "")
{
return string.Join(delimiter, list);
}
我々はgithubのレポをどのように作成する場合とhttpsを使用して、より簡単に、鉱山を私たちの取り組みを共有:// www.nuget.org/packages/System.Linq.Dynamic.Core/ –