This repository has been archived by the owner on Dec 14, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
FilterContext.cs
99 lines (91 loc) · 4.27 KB
/
FilterContext.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Mvc.Filters
{
/// <summary>
/// An abstract context for filters.
/// </summary>
public abstract class FilterContext : ActionContext
{
/// <summary>
/// Instantiates a new <see cref="FilterContext"/> instance.
/// </summary>
/// <param name="actionContext">The <see cref="ActionContext"/>.</param>
/// <param name="filters">All applicable <see cref="IFilterMetadata"/> implementations.</param>
public FilterContext(
ActionContext actionContext,
IList<IFilterMetadata> filters)
: base(actionContext)
{
if (filters == null)
{
throw new ArgumentNullException(nameof(filters));
}
Filters = filters;
}
/// <summary>
/// Gets all applicable <see cref="IFilterMetadata"/> implementations.
/// </summary>
public virtual IList<IFilterMetadata> Filters { get; }
/// <summary>
/// Returns a value indicating whether the provided <see cref="IFilterMetadata"/> is the most effective
/// policy (most specific) applied to the action associated with the <see cref="FilterContext"/>.
/// </summary>
/// <typeparam name="TMetadata">The type of the filter policy.</typeparam>
/// <param name="policy">The filter policy instance.</param>
/// <returns>
/// <c>true</c> if the provided <see cref="IFilterMetadata"/> is the most effective policy, otherwise <c>false</c>.
/// </returns>
/// <remarks>
/// <para>
/// The <see cref="IsEffectivePolicy{TMetadata}(TMetadata)"/> method is used to implement a common convention
/// for filters that define an overriding behavior. When multiple filters may apply to the same
/// cross-cutting concern, define a common interface for the filters (<typeparamref name="TMetadata"/>) and
/// implement the filters such that all of the implementations call this method to determine if they should
/// take action.
/// </para>
/// <para>
/// For instance, a global filter might be overridden by placing a filter attribute on an action method.
/// The policy applied directly to the action method could be considered more specific.
/// </para>
/// <para>
/// This mechanism for overriding relies on the rules of order and scope that the filter system
/// provides to control ordering of filters. It is up to the implementor of filters to implement this
/// protocol cooperatively. The filter system has no innate notion of overrides, this is a recommended
/// convention.
/// </para>
/// </remarks>
public bool IsEffectivePolicy<TMetadata>(TMetadata policy) where TMetadata : IFilterMetadata
{
if (policy == null)
{
throw new ArgumentNullException(nameof(policy));
}
var effective = FindEffectivePolicy<TMetadata>();
return ReferenceEquals(policy, effective);
}
/// <summary>
/// Returns the most effective (most specific) policy of type <typeparamref name="TMetadata"/> applied to
/// the action associated with the <see cref="FilterContext"/>.
/// </summary>
/// <typeparam name="TMetadata">The type of the filter policy.</typeparam>
/// <returns>The implementation of <typeparamref name="TMetadata"/> applied to the action associated with
/// the <see cref="FilterContext"/>
/// </returns>
public TMetadata FindEffectivePolicy<TMetadata>() where TMetadata : IFilterMetadata
{
// The most specific policy is the one closest to the action (nearest the end of the list).
for (var i = Filters.Count - 1; i >= 0; i--)
{
var filter = Filters[i];
if (filter is TMetadata match)
{
return match;
}
}
return default(TMetadata);
}
}
}