Skip to content

Commit

Permalink
Merge pull request #3792 from StefanOssendorf/dev/3756-add-checkRules…
Browse files Browse the repository at this point in the history
…Async-overloads

New overloads for CheckRulesAsync added
  • Loading branch information
rockfordlhotka committed Apr 14, 2024
2 parents 1f31199 + 593eb02 commit 4cece89
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 12 deletions.
10 changes: 10 additions & 0 deletions Source/Csla.test/ValidationRules/AsyncRuleRoot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,15 @@ private void Create()
{
BusinessRules.CheckRules();
}

[Create]
private void Create(string asyncAwaitValue)
{
using (BypassPropertyChecks) {
AsyncAwait = asyncAwaitValue;
}
}

public Task<List<string>> CheckRulesForPropertyAsyncAwait() => BusinessRules.CheckRulesAsync(AsyncAwaitProperty);
}
}
22 changes: 22 additions & 0 deletions Source/Csla.test/ValidationRules/AsyncRuleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
using UnitDriven;
using System.Threading.Tasks;
using Csla.TestHelpers;
using Csla.Rules;
using FluentAssertions.Execution;
using FluentAssertions;




#if NUNIT
using NUnit.Framework;
Expand Down Expand Up @@ -179,5 +185,21 @@ public async Task TestAsyncAwaitRule()
await tcs.Task;
}


[TestMethod]
public async Task MyTestMethod()
{
IDataPortal<AsyncRuleRoot> dataPortal = _testDIContext.CreateDataPortal<AsyncRuleRoot>();

var har = dataPortal.Create("SomeRandomText");
await har.WaitForIdle();

var affectedProperties = await har.CheckRulesForPropertyAsyncAwait();
using (new AssertionScope())
{
har.AsyncAwait.Should().Be("abc");
affectedProperties.Should().ContainSingle().Which.Should().Be(nameof(AsyncRuleRoot.AsyncAwait));
}
}
}
}
77 changes: 65 additions & 12 deletions Source/Csla/Rules/BusinessRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Threading.Tasks;
using Csla.Threading;
using Csla.Server;
using System.Threading;

namespace Csla.Rules
{
Expand Down Expand Up @@ -452,6 +453,52 @@ public bool CachePermissionResult(AuthorizationActions action, IMemberInfo eleme
return result;
}

/// <summary>
/// Invokes all rules for a specific property of the business type.
/// </summary>
/// <param name="property">Property to check.</param>
/// <returns>
/// Returns a list of property names affected by the invoked rules.
/// The PropertyChanged event should be raised for each affected
/// property.
/// </returns>
/// <exception cref="System.ArgumentNullException">If property is null</exception>
public async Task<List<string>> CheckRulesAsync(IPropertyInfo property)
{
return await CheckRulesAsync(property, Timeout.InfiniteTimeSpan);
}

/// <summary>
/// Invokes all rules for a specific property of the business type.
/// </summary>
/// <param name="property">Property to check.</param>
/// <param name="timeout">Timeout to wait for the rule completion.</param>
/// <returns>
/// Returns a list of property names affected by the invoked rules.
/// The PropertyChanged event should be raised for each affected
/// property.
/// </returns>
/// <exception cref="System.ArgumentNullException">If property is null</exception>
public async Task<List<string>> CheckRulesAsync(IPropertyInfo property, TimeSpan timeout)
{
var affectedProperties = CheckRules(property);
await WaitForAsyncRulesToComplete(timeout);
return affectedProperties;
}

/// <summary>
/// Invokes all rules for the business type.
/// </summary>
/// <returns>
/// Returns a list of property names affected by the invoked rules.
/// The PropertyChanged event should be raised for each affected
/// property. Does not return until all async rules are complete.
/// </returns>
public async Task<List<string>> CheckRulesAsync()
{
return await CheckRulesAsync(int.MaxValue);
}

/// <summary>
/// Invokes all rules for the business type.
/// </summary>
Expand All @@ -463,28 +510,35 @@ public bool CachePermissionResult(AuthorizationActions action, IMemberInfo eleme
/// </returns>
public async Task<List<string>> CheckRulesAsync(int timeout)
{
var result = CheckRules();
if (RunningAsyncRules)
{
var tasks = new Task[] { BusyChanged.WaitAsync(), Task.Delay(timeout) };
var final = await Task.WhenAny(tasks);
if (final == tasks[1])
throw new TimeoutException(nameof(CheckRulesAsync));
}
return result;
return await CheckRulesAsync(TimeSpan.FromMilliseconds(timeout));
}

/// <summary>
/// Invokes all rules for the business type.
/// </summary>
/// <param name="timeout">Timeout value.</param>
/// <returns>
/// Returns a list of property names affected by the invoked rules.
/// The PropertyChanged event should be raised for each affected
/// property. Does not return until all async rules are complete.
/// </returns>
public async Task<List<string>> CheckRulesAsync()
public async Task<List<string>> CheckRulesAsync(TimeSpan timeout)
{
return await CheckRulesAsync(int.MaxValue);
var result = CheckRules();
await WaitForAsyncRulesToComplete(timeout);
return result;
}

private async Task WaitForAsyncRulesToComplete(TimeSpan timeout) {
if (!RunningAsyncRules)
{
return;
}

var tasks = new Task[] { BusyChanged.WaitAsync(), Task.Delay(timeout) };
var final = await Task.WhenAny(tasks);
if (final == tasks[1])
throw new TimeoutException(nameof(CheckRulesAsync));
}

/// <summary>
Expand Down Expand Up @@ -527,7 +581,6 @@ public List<string> CheckObjectRules()
return CheckObjectRules(RuleContextModes.CheckObjectRules, true);
}


/// <summary>
/// Invokes all rules attached at the class level
/// of the business type.
Expand Down

0 comments on commit 4cece89

Please sign in to comment.