Skip to content

Commit 17aabf8

Browse files
authored
v3.28.0 (#130)
* v3.28.0 - *Enhancement:* Added extended capabilities to the `InvokeArgs` to allow additional customization. * Fix failing test.
1 parent 1dfcbda commit 17aabf8

File tree

10 files changed

+187
-64
lines changed

10 files changed

+187
-64
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
Represents the **NuGet** versions.
44

5+
## v3.28.0
6+
- *Enhancement:* Added extended capabilities to the `InvokeArgs` to allow additional customization.
7+
58
## v3.27.3
69
- *Fixed:* The `ExecutionContext.Messages` were not being returned as intended within the `x-messages` HTTP Response header; enabled within the `ExtendedStatusCodeResult` and `ExtendedContentResult` on success only (status code `>= 200` and `<= 299`). Note these messages are JSON serialized as the underlying `MessageItemCollection` type.
710
- *Fixed:* The `AgentTester` has been updated to return a `HttpResultAssertor` where the operation returns a `HttpResult` to enable further assertions to be made on the `Result` itself.

Common.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
3-
<Version>3.27.3</Version>
3+
<Version>3.28.0</Version>
44
<LangVersion>preview</LangVersion>
55
<Authors>Avanade</Authors>
66
<Company>Avanade</Company>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/CoreEx
2+
3+
using Microsoft.Extensions.Caching.Memory;
4+
5+
namespace CoreEx.Abstractions
6+
{
7+
/// <summary>
8+
/// Provides shareable internal capabilities.
9+
/// </summary>
10+
/// <remarks>This is intended for internal usage only; use with caution.</remarks>
11+
public static class Internal
12+
{
13+
private static IMemoryCache? _fallbackCache;
14+
15+
/// <summary>
16+
/// Gets the <b>CoreEx</b> fallback <see cref="IMemoryCache"/>.
17+
/// </summary>
18+
public static IMemoryCache MemoryCache => ExecutionContext.GetService<IInternalCache>() ?? (_fallbackCache ??= new MemoryCache(new MemoryCacheOptions()));
19+
20+
/// <summary>
21+
/// Represents a cache for internal capabilities.
22+
/// </summary>
23+
public interface IInternalCache : IMemoryCache { }
24+
}
25+
}

src/CoreEx/Abstractions/Reflection/PropertyExpression.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,10 @@ namespace CoreEx.Abstractions.Reflection
1616
/// </summary>
1717
public static partial class PropertyExpression
1818
{
19-
private static IMemoryCache? _fallbackCache;
20-
2119
/// <summary>
2220
/// Gets the <see cref="IMemoryCache"/>.
2321
/// </summary>
24-
internal static IMemoryCache Cache => ExecutionContext.GetService<IReflectionCache>() ?? (_fallbackCache ??= new MemoryCache(new MemoryCacheOptions()));
22+
internal static IMemoryCache Cache => ExecutionContext.GetService<IReflectionCache>() ?? Internal.MemoryCache;
2523

2624
/// <summary>
2725
/// Gets or sets the <see cref="IMemoryCache"/> absolute expiration <see cref="TimeSpan"/>.

src/CoreEx/Invokers/IInvoker.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/CoreEx
2+
3+
using System.Diagnostics;
4+
using System;
5+
using Microsoft.Extensions.Logging;
6+
7+
namespace CoreEx.Invokers
8+
{
9+
/// <summary>
10+
/// Enables the standardized invoker capabilities.
11+
/// </summary>
12+
public interface IInvoker
13+
{
14+
/// <summary>
15+
/// Gets the start of an <see cref="Activity"/> action.
16+
/// </summary>
17+
Action<InvokeArgs>? OnActivityStart { get; }
18+
19+
/// <summary>
20+
/// Gets the <see cref="Activity"/> <see cref="Exception"/> action.
21+
/// </summary>
22+
Action<InvokeArgs, Exception>? OnActivityException { get; }
23+
24+
/// <summary>
25+
/// Gets the completion of an <see cref="Activity"/> action.
26+
/// </summary>
27+
Action<InvokeArgs>? OnActivityComplete { get; }
28+
29+
/// <summary>
30+
/// Get the caller information <see cref="ILogger"/> formatter.
31+
/// </summary>
32+
Func<InvokeArgs, string> CallerLoggerFormatter { get; }
33+
}
34+
}

src/CoreEx/Invokers/InvokeArgs.cs

Lines changed: 87 additions & 50 deletions
Large diffs are not rendered by default.

src/CoreEx/Invokers/InvokerBaseT.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/CoreEx
22

33
using System;
4+
using System.Diagnostics;
45
using System.Runtime.CompilerServices;
56
using System.Threading;
67
using System.Threading.Tasks;
@@ -13,8 +14,20 @@ namespace CoreEx.Invokers
1314
/// <typeparam name="TInvoker">The owner (invoking) <see cref="Type"/>.</typeparam>
1415
/// <remarks>All public methods result in either the synchronous <see cref="OnInvoke"/> or asynchronous <see cref="OnInvokeAsync"/>virtual methods being called to manage the underlying invocation; therefore, where overridding each should
1516
/// be overridden with the same logic. Where no result is specified this defaults to '<c>object?</c>' for the purposes of execution.</remarks>
16-
public abstract class InvokerBase<TInvoker>
17+
public abstract class InvokerBase<TInvoker> : IInvoker
1718
{
19+
/// <inheritdoc/>
20+
public Action<InvokeArgs>? OnActivityStart { get; protected set; }
21+
22+
/// <inheritdoc/>
23+
public Action<InvokeArgs, Exception>? OnActivityException { get; protected set; }
24+
25+
/// <inheritdoc/>
26+
public Action<InvokeArgs>? OnActivityComplete { get; protected set; }
27+
28+
/// <inheritdoc/>
29+
public Func<InvokeArgs, string> CallerLoggerFormatter { get; protected set; } = InvokeArgs.DefaultCallerLogFormatter;
30+
1831
/// <summary>
1932
/// Invokes a <paramref name="func"/> with a <typeparamref name="TResult"/> synchronously.
2033
/// </summary>
@@ -41,7 +54,7 @@ public abstract class InvokerBase<TInvoker>
4154
/// </summary>
4255
private TResult TraceOnInvoke<TResult>(TInvoker invoker, Func<InvokeArgs, TResult> func, string? memberName)
4356
{
44-
var ia = new InvokeArgs(GetType(), invoker?.GetType(), memberName, null);
57+
var ia = new InvokeArgs(this, invoker, memberName, null);
4558
try
4659
{
4760
return ia.TraceResult(OnInvoke(ia, invoker, func));
@@ -62,7 +75,7 @@ private TResult TraceOnInvoke<TResult>(TInvoker invoker, Func<InvokeArgs, TResul
6275
/// </summary>
6376
private async Task<TResult> TraceOnInvokeAsync<TResult>(TInvoker invoker, Func<InvokeArgs, CancellationToken, Task<TResult>> func, string? memberName, CancellationToken cancellationToken)
6477
{
65-
var ia = new InvokeArgs(GetType(), invoker?.GetType(), memberName, null);
78+
var ia = new InvokeArgs(this, invoker, memberName, null);
6679
try
6780
{
6881
return ia.TraceResult(await OnInvokeAsync(ia, invoker, func, cancellationToken).ConfigureAwait(false));

src/CoreEx/Invokers/InvokerBaseT2.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/CoreEx
22

33
using System;
4+
using System.Diagnostics;
45
using System.Runtime.CompilerServices;
56
using System.Threading;
67
using System.Threading.Tasks;
@@ -14,8 +15,20 @@ namespace CoreEx.Invokers
1415
/// <typeparam name="TArgs">The arguments <see cref="Type"/>.</typeparam>
1516
/// <remarks>All public methods result in either the synchronous <see cref="OnInvoke"/> or asynchronous <see cref="OnInvokeAsync"/> virtual methods being called to manage the underlying invocation; therefore, where overridding each should
1617
/// be overridden with the same logic. Where no result is specified this defaults to '<c>object?</c>' for the purposes of execution.</remarks>
17-
public abstract class InvokerBase<TInvoker, TArgs>
18+
public abstract class InvokerBase<TInvoker, TArgs> : IInvoker
1819
{
20+
/// <inheritdoc/>
21+
public Action<InvokeArgs>? OnActivityStart { get; protected set; }
22+
23+
/// <inheritdoc/>
24+
public Action<InvokeArgs, Exception>? OnActivityException { get; protected set; }
25+
26+
/// <inheritdoc/>
27+
public Action<InvokeArgs>? OnActivityComplete { get; protected set; }
28+
29+
/// <inheritdoc/>
30+
public Func<InvokeArgs, string> CallerLoggerFormatter { get; protected set; } = InvokeArgs.DefaultCallerLogFormatter;
31+
1932
/// <summary>
2033
/// Invokes a <paramref name="func"/> with a <typeparamref name="TResult"/> synchronously.
2134
/// </summary>
@@ -44,7 +57,7 @@ public abstract class InvokerBase<TInvoker, TArgs>
4457
/// </summary>
4558
private TResult TraceOnInvoke<TResult>(TInvoker invoker, Func<InvokeArgs, TResult> func, TArgs? args, string? memberName)
4659
{
47-
var ia = new InvokeArgs(GetType(), invoker?.GetType(), memberName, null);
60+
var ia = new InvokeArgs(this, invoker, memberName, null);
4861
try
4962
{
5063
return ia.TraceResult(OnInvoke(ia, invoker, func, args));
@@ -65,7 +78,7 @@ private TResult TraceOnInvoke<TResult>(TInvoker invoker, Func<InvokeArgs, TResul
6578
/// </summary>
6679
private async Task<TResult> TraceOnInvokeAsync<TResult>(TInvoker invoker, Func<InvokeArgs, CancellationToken, Task<TResult>> func, TArgs? args, string? memberName, CancellationToken cancellationToken)
6780
{
68-
var ia = new InvokeArgs(GetType(), invoker?.GetType(), memberName, null);
81+
var ia = new InvokeArgs(this, invoker, memberName, null);
6982
try
7083
{
7184
return ia.TraceResult(await OnInvokeAsync(ia, invoker, func, args, cancellationToken).ConfigureAwait(false));

src/CoreEx/RefData/ReferenceDataOrchestrator.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ public ReferenceDataOrchestrator Register<TProvider>() where TProvider : IRefere
276276

277277
Logger.LogDebug("Reference data type {RefDataType} cache load start: ServiceProvider.CreateScope and Threading.ExecutionContext.SuppressFlow to support underlying cache data get.", type.FullName);
278278
using var ec = ExecutionContext.Current.CreateCopy();
279-
var rdo = _asyncLocal.Value;
279+
var rdo = this;
280280

281281
using var scope = ServiceProvider.CreateScope();
282282
Task<IReferenceDataCollection> task;
@@ -301,15 +301,15 @@ public ReferenceDataOrchestrator Register<TProvider>() where TProvider : IRefere
301301
/// <summary>
302302
/// Performs the actual reference data load in a new thread context / scope.
303303
/// </summary>
304-
private async Task<IReferenceDataCollection> GetByTypeInNewScopeAsync(ReferenceDataOrchestrator? rdo, ExecutionContext executionContext, IServiceScope scope, Type type, Type providerType, InvokeArgs invokeArgs, CancellationToken cancellationToken)
304+
private async Task<IReferenceDataCollection> GetByTypeInNewScopeAsync(ReferenceDataOrchestrator rdo, ExecutionContext executionContext, IServiceScope scope, Type type, Type providerType, InvokeArgs invokeArgs, CancellationToken cancellationToken)
305305
{
306306
_asyncLocal.Value = rdo;
307307

308308
executionContext.ServiceProvider = scope.ServiceProvider;
309309
ExecutionContext.SetCurrent(executionContext);
310310

311311
// Start related activity as this "work" is occuring on an unrelated different thread (by design to ensure complete separation).
312-
var ria = invokeArgs.StartNewRelated(typeof(ReferenceDataOrchestratorInvoker), typeof(ReferenceDataOrchestrator), nameof(GetByTypeInNewScopeAsync));
312+
var ria = invokeArgs.StartNewRelated(invokeArgs.Invoker, rdo, nameof(GetByTypeInNewScopeAsync));
313313
try
314314
{
315315
if (ria.Activity is not null)

tests/CoreEx.Test/Framework/Invokers/InvokerBaseTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public void Invoke_AsyncWithResult()
3636
public async Task Invoke_AsyncWithResult_Load()
3737
{
3838
var i = new TestInvoker();
39-
for (var j = 0; j < 1000; j++)
39+
for (var j = 0; j < 100000; j++)
4040
{
4141
await i.InvokeAsync(this, async (_, ct) => { await Task.Delay(0, ct); return 88; });
4242
}

0 commit comments

Comments
 (0)