9using System.Collections.Generic;
11using System.Reflection;
13using System.Runtime.Loader;
27 private static Lazy<System.Collections.Concurrent.ConcurrentDictionary<RuleSetKey, Tuple<string, AuthorizationRuleManager>>> _perTypeRules =
28 new Lazy<System.Collections.Concurrent.ConcurrentDictionary<RuleSetKey, Tuple<string, AuthorizationRuleManager>>>();
30 private static Lazy<System.Collections.Concurrent.ConcurrentDictionary<RuleSetKey,
AuthorizationRuleManager>> _perTypeRules =
39 var key =
new RuleSetKey { Type = type, RuleSet = ruleSet };
42 var rulesInfo = _perTypeRules.Value
45 (t) => AssemblyLoadContextManager.CreateCacheInstance(type,
new AuthorizationRuleManager(), OnAssemblyLoadContextUnload)
48 var result = rulesInfo.Item2;
53 InitializePerTypeRules(applicationContext, result, type);
58 private bool InitializingPerType {
get;
set; }
67 if (RulesExistForType(type))
75 mgr.InitializingPerType =
true;
78 System.Reflection.MethodInfo method = FindObjectAuthorizationRulesMethod(type);
81 if (method.GetParameters().Length == 0)
82 method.Invoke(
null,
null);
83 else if (applicationContext !=
null)
86 throw new InvalidOperationException(
87 $
"{nameof(InitializePerTypeRules)} {nameof(applicationContext)} == null");
94 CleanupRulesForType(type);
99 mgr.InitializingPerType =
false;
104 private static System.Reflection.MethodInfo FindObjectAuthorizationRulesMethod(Type type)
106 System.Reflection.MethodInfo method;
107 method = type.GetMethods().Where(
108 m => m.IsStatic && m.CustomAttributes.Where(
113 const BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
114 method = type.GetMethod(
"AddObjectAuthorizationRules", flags);
119 private static bool RulesExistForType(Type type)
124 return _perTypeRules.Value.Count(value => value.Key.Type == type) > 1;
129 private static void CleanupRulesForType(Type type)
135 var typeRules = _perTypeRules.Value.Where(value => value.Key.Type == type);
136 foreach (var key
in typeRules)
138 _perTypeRules.Value.TryRemove(key.Key, out _);
143 private class RuleSetKey
145 public Type Type {
get;
set; }
146 public string RuleSet {
get;
set; }
148 public override bool Equals(
object obj)
150 var other = obj as RuleSetKey;
154 return this.Type.Equals(other.Type) && RuleSet == other.RuleSet;
157 public override int GetHashCode()
159 return (this.Type.FullName + RuleSet).GetHashCode();
166 public List<IAuthorizationRule>
Rules {
get;
private set; }
181 Rules =
new List<IAuthorizationRule>();
185 private static void OnAssemblyLoadContextUnload(AssemblyLoadContext context)
188 AssemblyLoadContextManager.RemoveFromCache(_perTypeRules.Value, context,
true);
Provides consistent context information between the client and server DataPortal objects.
const string DefaultRuleSet
The default RuleSet name
Attribute identifying static method invoked to add object authorization rules for type.
Context for the AddObjectAuthorizationRulesContext method.
Manages the list of authorization rules for a business type.
bool Initialized
Gets or sets a value indicating whether the rules have been initialized.
bool InitializedPerType
Gets or sets a value indicating whether the rules have been initialized.
List< IAuthorizationRule > Rules
Gets the list of rule objects for the business type.
@ Any
Default value, rule can run in any context