CSLA.NET 5.4.2
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
RuleContext.cs
Go to the documentation of this file.
1//-----------------------------------------------------------------------
2// <copyright file="RuleContext.cs" company="Marimer LLC">
3// Copyright (c) Marimer LLC. All rights reserved.
4// Website: https://cslanet.com
5// </copyright>
6// <summary>Context information provided to a business rule</summary>
7//-----------------------------------------------------------------------
8using System;
9using System.ComponentModel;
10using System.Collections.Generic;
11using System.Linq;
12using System.Text;
13using Csla.Core;
14using Csla.Properties;
15using Csla.Threading;
16
17namespace Csla.Rules
18{
22 [Flags]
23 public enum RuleContextModes
24 {
28 Any = 247,
32 CheckRules = 1,
45 }
46
52 {
56 [EditorBrowsable(EditorBrowsableState.Never)]
57 public IBusinessRuleBase Rule { get; internal set; }
58
62 public object Target { get; internal set; }
63
68 public Dictionary<Csla.Core.IPropertyInfo, object> InputPropertyValues { get; internal set; }
69
70 private LazySingleton<List<IPropertyInfo>> _dirtyProperties;
77 [EditorBrowsable(EditorBrowsableState.Never)]
78 public List<IPropertyInfo> DirtyProperties
79 {
80 get
81 {
82 if (!_dirtyProperties.IsValueCreated)
83 return null;
84 return _dirtyProperties.Value;
85 }
86 }
87
88 private readonly LazySingleton<Dictionary<IPropertyInfo, object>> _outputPropertyValues;
93 [EditorBrowsable(EditorBrowsableState.Never)]
94 public Dictionary<Csla.Core.IPropertyInfo, object> OutputPropertyValues
95 {
96 get
97 {
98 if (!_outputPropertyValues.IsValueCreated)
99 return null;
100 return _outputPropertyValues.Value;
101 }
102 }
103
108 private List<RuleResult> _results;
113 [EditorBrowsable(EditorBrowsableState.Never)]
114 public List<RuleResult> Results
115 {
116 get
117 {
118 if (_results == null)
119 _results = new List<RuleResult>();
120 return _results;
121 }
122 private set
123 {
124 _results = value;
125 }
126 }
127
128 private readonly Action<IRuleContext> _completeHandler;
129
134 [EditorBrowsable(EditorBrowsableState.Never)]
135 public string OriginPropertyName { get; internal set; }
136
141 public RuleContextModes ExecuteContext { get; internal set; }
142
143
149 public void ExecuteRule(IBusinessRuleBase innerRule)
150 {
151 var chainedContext = GetChainedContext(innerRule);
152 if (BusinessRules.CanRunRule(innerRule, chainedContext.ExecuteContext))
153 {
154 if (innerRule is IBusinessRule syncRule)
155 syncRule.Execute(chainedContext);
156 else if (innerRule is IBusinessRuleAsync asyncRule)
157 asyncRule.ExecuteAsync(chainedContext).ContinueWith((t) => { chainedContext.Complete(); });
158 else
159 throw new ArgumentOutOfRangeException(innerRule.GetType().FullName);
160 }
161 }
162
169 [EditorBrowsable(EditorBrowsableState.Never)]
171 {
172 get { return (ExecuteContext & RuleContextModes.AsAffectedPoperty) > 0; }
173 }
174
181 [EditorBrowsable(EditorBrowsableState.Never)]
183 {
184 get { return (ExecuteContext & RuleContextModes.PropertyChanged) > 0; }
185 }
186
193 [EditorBrowsable(EditorBrowsableState.Never)]
195 {
196 get { return (ExecuteContext & RuleContextModes.CheckRules) > 0; }
197 }
198
205 [EditorBrowsable(EditorBrowsableState.Never)]
207 {
208 get { return (ExecuteContext & RuleContextModes.CheckObjectRules) > 0; }
209 }
210
211 internal RuleContext(Action<IRuleContext> completeHandler)
212 {
213 _completeHandler = completeHandler;
214 _outputPropertyValues = new LazySingleton<Dictionary<IPropertyInfo, object>>();
215 _dirtyProperties = new LazySingleton<List<IPropertyInfo>>();
216 }
217
218 internal RuleContext(Action<IRuleContext> completeHandler, RuleContextModes executeContext) : this(completeHandler)
219 {
220 ExecuteContext = executeContext;
221 }
222
223 internal RuleContext(Action<IRuleContext> completeHandler, LazySingleton<Dictionary<IPropertyInfo, object>> outputPropertyValues, LazySingleton<List<IPropertyInfo>> dirtyProperties, RuleContextModes executeContext)
224 {
225 _completeHandler = completeHandler;
226 _outputPropertyValues = outputPropertyValues;
227 _dirtyProperties = dirtyProperties;
228 ExecuteContext = executeContext;
229 }
230
238 public RuleContext(Action<IRuleContext> completeHandler, IBusinessRuleBase rule, object target, Dictionary<Csla.Core.IPropertyInfo, object> inputPropertyValues)
239 : this(completeHandler)
240 {
241 Rule = rule;
242 if (rule.PrimaryProperty != null)
244 Target = target;
245 InputPropertyValues = inputPropertyValues;
246 ExecuteContext = RuleContextModes.PropertyChanged;
247 }
248
261 {
262 var result = new RuleContext(_completeHandler, _outputPropertyValues, _dirtyProperties, ExecuteContext);
263 result.Rule = rule;
264 result.OriginPropertyName = OriginPropertyName;
265 result.InputPropertyValues = InputPropertyValues;
266 result.Results = Results;
267
268 if (!rule.IsAsync || rule.ProvideTargetWhenAsync)
269 result.Target = Target;
270 return result;
271 }
272
278 public void AddErrorResult(string description)
279 {
280 Results.Add(new RuleResult(Rule.RuleName, Rule.PrimaryProperty, description));
281 }
282
290 public void AddErrorResult(string description, bool stopProcessing)
291 {
292 Results.Add(new RuleResult(Rule.RuleName, Rule.PrimaryProperty, description) { StopProcessing = stopProcessing });
293 }
294
303 public void AddErrorResult(Csla.Core.IPropertyInfo property, string description)
304 {
305 if (!Rule.AffectedProperties.Contains(property))
306 throw new ArgumentOutOfRangeException(property.Name, string.Format(Resources.PropertyNotInAffectedPropertiesException, property.Name));
307 Results.Add(new RuleResult(Rule.RuleName, property, description));
308 }
309
315 public void AddWarningResult(string description)
316 {
317 Results.Add(new RuleResult(Rule.RuleName, Rule.PrimaryProperty, description) { Severity = RuleSeverity.Warning });
318 }
319
327 public void AddWarningResult(string description, bool stopProcessing)
328 {
329 Results.Add(new RuleResult(Rule.RuleName, Rule.PrimaryProperty, description) { Severity = RuleSeverity.Warning, StopProcessing = stopProcessing });
330 }
331
332
340 public void AddWarningResult(Csla.Core.IPropertyInfo property, string description)
341 {
342 if (!Rule.AffectedProperties.Contains(property))
343 throw new ArgumentOutOfRangeException(property.Name, string.Format(Resources.PropertyNotInAffectedPropertiesException, property.Name));
344 Results.Add(new RuleResult(Rule.RuleName, property, description) { Severity = RuleSeverity.Warning });
345 }
346
352 public void AddInformationResult(string description)
353 {
354 Results.Add(new RuleResult(Rule.RuleName, Rule.PrimaryProperty, description) { Severity = RuleSeverity.Information });
355 }
356
362 public void AddInformationResult(string description, bool stopProcessing)
363 {
364 Results.Add(new RuleResult(Rule.RuleName, Rule.PrimaryProperty, description) { Severity = RuleSeverity.Information, StopProcessing = stopProcessing });
365 }
366
374 public void AddInformationResult(Csla.Core.IPropertyInfo property, string description)
375 {
376 if (!Rule.AffectedProperties.Contains(property))
377 throw new ArgumentOutOfRangeException(property.Name, string.Format(Resources.PropertyNotInAffectedPropertiesException, property.Name));
378 Results.Add(new RuleResult(Rule.RuleName, property, description) { Severity = RuleSeverity.Information });
379 }
380
385 public void AddSuccessResult(bool stopProcessing)
386 {
387 Results.Add(new RuleResult(Rule.RuleName, Rule.PrimaryProperty) { Severity = RuleSeverity.Success, StopProcessing = stopProcessing });
388 }
389
395 public void AddOutValue(object value)
396 {
397 _outputPropertyValues.Value.Add(Rule.PrimaryProperty, value);
398 }
399
407 public void AddOutValue(Csla.Core.IPropertyInfo property, object value)
408 {
409 _outputPropertyValues.Value[property] = value;
410 }
411
412
418 [EditorBrowsable(EditorBrowsableState.Never)]
420 {
421 if (!Rule.AffectedProperties.Contains(property))
422 throw new ArgumentOutOfRangeException(property.Name, string.Format(Resources.PropertyNotInAffectedPropertiesException, property.Name));
423 _dirtyProperties.Value.Add(property);
424 }
425
431 public void Complete()
432 {
433 if (Results.Count == 0)
435 _completeHandler?.Invoke(this);
436 }
437
444 public T GetInputValue<T>(PropertyInfo<T> propertyInfo)
445 {
446 return (T)InputPropertyValues[propertyInfo];
447 }
448
455 public T GetInputValue<T>(IPropertyInfo propertyInfo)
456 {
457 return (T)InputPropertyValues[propertyInfo];
458 }
459
467 public bool TryGetInputValue<T>(PropertyInfo<T> propertyInfo, ref T value)
468 {
469 if (!InputPropertyValues.ContainsKey(propertyInfo))
470 {
471 value = default(T);
472 return false;
473 }
474
475 value = (T)InputPropertyValues[propertyInfo];
476 return true;
477 }
478
486 public bool TryGetInputValue<T>(IPropertyInfo propertyInfo, ref T value)
487 {
488 if (!InputPropertyValues.ContainsKey(propertyInfo))
489 {
490 value = default(T);
491 return false;
492 }
493
494 value = (T)InputPropertyValues[propertyInfo];
495 return true;
496 }
497 }
498}
An alternative to Lazy<T>
T Value
Gets the instance.
bool IsValueCreated
Gets a value indicating whether this instance is initilized and contains a value.
A strongly-typed resource class, for looking up localized strings, etc.
static string PropertyNotInAffectedPropertiesException
Looks up a localized string similar to Property {0} must be added to AffectedProperties.
Maintains metadata about a property.
Tracks the business rules for a business object.
Context information provided to a business rule when it is invoked.
Definition: RuleContext.cs:52
void AddWarningResult(string description)
Add a Warning severity result to the Results list.
Definition: RuleContext.cs:315
void AddSuccessResult(bool stopProcessing)
Add a Success severity result to the Results list.
Definition: RuleContext.cs:385
object Target
Gets a reference to the target business object.
Definition: RuleContext.cs:62
Dictionary< Csla.Core.IPropertyInfo, object > OutputPropertyValues
Gets a dictionary containing copies of property values that should be updated in the target object.
Definition: RuleContext.cs:95
List< IPropertyInfo > DirtyProperties
Gets a list of dirty properties (value was updated).
Definition: RuleContext.cs:79
bool IsPropertyChangedContext
Gets a value indicating whether this instance is property changed context.
Definition: RuleContext.cs:183
bool IsCheckObjectRulesContext
Gets a value indicating whether this instance is check object rules context.
Definition: RuleContext.cs:207
void AddErrorResult(Csla.Core.IPropertyInfo property, string description)
Add a Error severity result to the Results list.
Definition: RuleContext.cs:303
List< RuleResult > Results
Gets a list of RuleResult objects containing the results of the rule.
Definition: RuleContext.cs:115
void AddWarningResult(string description, bool stopProcessing)
Add a Warning severity result to the Results list.
Definition: RuleContext.cs:327
RuleContextModes ExecuteContext
Gets the execution context.
Definition: RuleContext.cs:141
void AddErrorResult(string description)
Add a Error severity result to the Results list.
Definition: RuleContext.cs:278
void AddWarningResult(Csla.Core.IPropertyInfo property, string description)
Add a Warning severity result to the Results list.
Definition: RuleContext.cs:340
void AddErrorResult(string description, bool stopProcessing)
Add a Error severity result to the Results list.
Definition: RuleContext.cs:290
bool TryGetInputValue< T >(PropertyInfo< T > propertyInfo, ref T value)
Tries to get the value.
Definition: RuleContext.cs:467
void ExecuteRule(IBusinessRuleBase innerRule)
Executes the inner rule from the outer rules context.
Definition: RuleContext.cs:149
void AddOutValue(Csla.Core.IPropertyInfo property, object value)
Add an outbound value to update a property on the business object once the rule is complete.
Definition: RuleContext.cs:407
void Complete()
Indicates that the rule processing is complete, so CSLA .NET will process the Results list.
Definition: RuleContext.cs:431
RuleContext(Action< IRuleContext > completeHandler, IBusinessRuleBase rule, object target, Dictionary< Csla.Core.IPropertyInfo, object > inputPropertyValues)
Creates a RuleContext instance for testing.
Definition: RuleContext.cs:238
void AddDirtyProperty(Csla.Core.IPropertyInfo property)
Adds a property name as a dirty field (changed value).
Definition: RuleContext.cs:419
void AddInformationResult(string description, bool stopProcessing)
Add an Information severity result to the Results list.
Definition: RuleContext.cs:362
void AddInformationResult(string description)
Add an Information severity result to the Results list.
Definition: RuleContext.cs:352
Dictionary< Csla.Core.IPropertyInfo, object > InputPropertyValues
Gets a dictionary containing copies of property values from the target business object.
Definition: RuleContext.cs:68
IRuleContext GetChainedContext(IBusinessRuleBase rule)
Gets a new RuleContext object for a chained rule.
Definition: RuleContext.cs:260
string OriginPropertyName
Gets or sets the name of the origin property.
Definition: RuleContext.cs:135
bool IsCascadeContext
Gets a value indicating whether this instance is cascade context as a result of AffectedProperties.
Definition: RuleContext.cs:171
void AddOutValue(object value)
Add an outbound value to update the rule's primary property on the business object once the rule is c...
Definition: RuleContext.cs:395
IBusinessRuleBase Rule
Gets the rule object.
Definition: RuleContext.cs:57
bool IsCheckRulesContext
Gets a value indicating whether this instance is check rules context.
Definition: RuleContext.cs:195
void AddInformationResult(Csla.Core.IPropertyInfo property, string description)
Add an Information severity result to the Results list.
Definition: RuleContext.cs:374
T GetInputValue< T >(PropertyInfo< T > propertyInfo)
Gets the value.
Definition: RuleContext.cs:444
Contains information about the result of a rule.
Definition: RuleResult.cs:20
string Name
Gets the member name value.
Definition: IMemberInfo.cs:23
Maintains metadata about a property.
Interface defining a business/validation rule implementation.
Interface defining a business/validation rule implementation.
bool IsAsync
Gets a value indicating whether the Execute() method will run asynchronous code.
bool ProvideTargetWhenAsync
Gets a value indicating that the Target property should be set even for an async rule (note that usin...
List< Csla.Core.IPropertyInfo > AffectedProperties
Gets a list of properties affected by this rule.
Csla.Core.IPropertyInfo PrimaryProperty
Gets the primary property affected by this rule.
string RuleName
Gets a unique rule:// URI for the specific instance of the rule within the context of the business ob...
Interface defining a business/validation rule implementation.
Context information provided to a business rule when it is invoked.
Definition: IRuleContext.cs:20
RuleContextModes
RuleContext mode flags
Definition: RuleContext.cs:24
@ PropertyChanged
Called from PropertyHasChanged event on BO but not including cascade calls by AffectedProperties
@ CheckObjectRules
Called from CheckObjectRules
@ AsAffectedPoperty
Include cascaded calls by AffectedProperties
@ CheckRules
Called from CheckRules
@ Any
Default value, rule can run in any context