-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enables a custom expression serializer, and… (#98)
Enables a custom expression serializer, and also a baseclass for just adding known types to the Serialize.Linq JsonSerialize
- Loading branch information
Showing
12 changed files
with
384 additions
and
37 deletions.
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
src/BlazorWorker.Demo/Net8/Client/BlazorWorker.Demo.Client/Pages/ComplexSerialization.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
@page "/ComplexSerialization" | ||
<BlazorWorker.Demo.SharedPages.Pages.ComplexSerialization /> |
133 changes: 133 additions & 0 deletions
133
src/BlazorWorker.Demo/SharedPages/Pages/ComplexSerialization.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
@inject IWorkerFactory workerFactory | ||
|
||
@using BlazorWorker.BackgroundServiceFactory | ||
@using BlazorWorker.WorkerBackgroundService | ||
@using BlazorWorker.Demo.Shared | ||
@using BlazorWorker.Core | ||
<div class="row"> | ||
<div class="col-6 col-xs-12"> | ||
<h1>.NET Worker Multithreading</h1> | ||
|
||
Complex / Custom Serialization <br /> | ||
<br /><br /> | ||
<button @onclick="OnClick" class="btn btn-primary">Run Test</button><br /> | ||
|
||
<br /> | ||
<br /> | ||
<strong>Output:</strong> | ||
<hr /> | ||
<pre> | ||
@output | ||
</pre> | ||
</div> | ||
<div class="col-6 col-xs-12"> | ||
<GithubSource RelativePath="Pages/BackgroundServiceMulti.razor" /> | ||
</div> | ||
</div> | ||
@code { | ||
|
||
string output; | ||
|
||
IWorker worker; | ||
IWorkerBackgroundService<ComplexService> backgroundService; | ||
|
||
string RunDisabled => Running ? "disabled" : null; | ||
bool Running = false; | ||
|
||
|
||
public class ComplexService | ||
{ | ||
public ComplexServiceResponse ComplexCall(ComplexServiceArg arg) | ||
{ | ||
return new ComplexServiceResponse | ||
{ | ||
OriginalArg = arg, | ||
OnlyInResponse = "This is only in response." | ||
}; | ||
} | ||
} | ||
|
||
public class ComplexServiceArg | ||
{ | ||
public string ThisIsJustAString { get; set; } | ||
public OhLookARecord ARecord { get; set; } | ||
public Dictionary<string, string> ADictionary { get; set; } | ||
public ComplexServiceArg TypeRecursive { get; set; } | ||
} | ||
|
||
public class ComplexServiceResponse | ||
{ | ||
public ComplexServiceArg OriginalArg { get; set; } | ||
public string OnlyInResponse { get; set; } | ||
} | ||
|
||
public record OhLookARecord | ||
{ | ||
public int Number { get; set; } | ||
} | ||
|
||
public async Task OnClick(EventArgs _) | ||
{ | ||
Running = true; | ||
await this.InvokeAsync(StateHasChanged); | ||
|
||
output = ""; | ||
var rn = Environment.NewLine; | ||
try | ||
{ | ||
if (worker == null) | ||
{ | ||
output += $"Starting worker...{rn}"; | ||
await this.InvokeAsync(StateHasChanged); | ||
worker = await workerFactory.CreateAsync(); | ||
} | ||
if (backgroundService == null) | ||
{ | ||
|
||
output += $"Starting BackgroundService...{rn}"; | ||
await this.InvokeAsync(StateHasChanged); | ||
/* | ||
* have a look here. This is the essence of this example. | ||
* */ | ||
|
||
backgroundService = await worker.CreateBackgroundServiceAsync<ComplexService>(options | ||
=> options.UseCustomExpressionSerializer(typeof(CustomSerializeLinqExpressionJsonSerializer))); | ||
} | ||
|
||
var sw = System.Diagnostics.Stopwatch.StartNew(); | ||
|
||
var complexArgInstance = new ComplexServiceArg | ||
{ | ||
ThisIsJustAString = "just a string", | ||
ARecord = new OhLookARecord { Number = 5 }, | ||
ADictionary = new Dictionary<string, string> | ||
{ | ||
{ "Test", "TestValue" } | ||
}, | ||
TypeRecursive = new ComplexServiceArg | ||
{ | ||
ThisIsJustAString = "SubString" | ||
} | ||
}; | ||
|
||
var result = await backgroundService.RunAsync(service => service.ComplexCall(complexArgInstance)); | ||
var elapsed = sw.ElapsedMilliseconds; | ||
output += $"{rn}result: " + System.Text.Json.JsonSerializer.Serialize(result); | ||
output += $"{rn}roundtrip to worker in {elapsed}ms"; | ||
} | ||
catch (Exception e) | ||
{ | ||
output += $"{rn}Error = {e}"; | ||
} | ||
finally | ||
{ | ||
Running = false; | ||
output += $"{rn}Done."; | ||
} | ||
} | ||
|
||
private string LogDate() | ||
{ | ||
return DateTime.Now.ToString("HH:mm:ss:fff"); | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
src/BlazorWorker.Demo/SharedPages/Shared/CustomExpressionSerializer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
using BlazorWorker.WorkerBackgroundService; | ||
using Serialize.Linq.Serializers; | ||
using System; | ||
using System.Linq.Expressions; | ||
using static BlazorWorker.Demo.SharedPages.Pages.ComplexSerialization; | ||
|
||
namespace BlazorWorker.Demo.SharedPages.Shared | ||
{ | ||
/// <summary> | ||
/// Example 1: Simple custom expression Serializer using <see cref="Serialize.Linq.ExpressionSerializer"/> | ||
/// as base class, but explicitly adds complex types as known types. | ||
/// </summary> | ||
public class CustomSerializeLinqExpressionJsonSerializer : SerializeLinqExpressionJsonSerializerBase | ||
{ | ||
public override Type[] GetKnownTypes() => | ||
[typeof(ComplexServiceArg), typeof(ComplexServiceResponse), typeof(OhLookARecord)]; | ||
} | ||
|
||
/// <summary> | ||
/// Fully custom Expression Serializer, which uses <see cref="Serialize.Linq.ExpressionSerializer"/> but you could use an alternative implementation. | ||
/// </summary> | ||
public class CustomExpressionSerializer : IExpressionSerializer | ||
{ | ||
private readonly ExpressionSerializer serializer; | ||
|
||
public CustomExpressionSerializer() | ||
{ | ||
var specificSerializer = new JsonSerializer(); | ||
specificSerializer.AddKnownType(typeof(ComplexServiceArg)); | ||
specificSerializer.AddKnownType(typeof(ComplexServiceResponse)); | ||
specificSerializer.AddKnownType(typeof(OhLookARecord)); | ||
|
||
this.serializer = new ExpressionSerializer(specificSerializer); | ||
} | ||
|
||
public Expression Deserialize(string expressionString) | ||
{ | ||
return serializer.DeserializeText(expressionString); | ||
} | ||
|
||
public string Serialize(Expression expression) | ||
{ | ||
return serializer.SerializeText(expression); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
src/BlazorWorker.ServiceFactory/BlazorWorker.BackgroundServiceFactory.xml
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using BlazorWorker.Core; | ||
using BlazorWorker.WorkerBackgroundService; | ||
using System; | ||
|
||
namespace BlazorWorker.BackgroundServiceFactory | ||
{ | ||
public static class WorkerInitExtension | ||
{ | ||
|
||
/// <summary> | ||
/// Sets a custom ExpressionSerializer type. Must implement <see cref="IExpressionSerializer"/>.. | ||
/// </summary> | ||
/// <param name="source"></param> | ||
/// <param name="expressionSerializerType">A type that implements <see cref="IExpressionSerializer"/></param> | ||
/// <returns></returns> | ||
/// <exception cref="ArgumentNullException"></exception> | ||
public static WorkerInitOptions UseCustomExpressionSerializer(this WorkerInitOptions source, Type expressionSerializerType) | ||
{ | ||
if (source == null) | ||
{ | ||
throw new ArgumentNullException(nameof(source)); | ||
} | ||
|
||
source.SetEnv(WebWorkerOptions.ExpressionSerializerTypeEnvKey, expressionSerializerType.AssemblyQualifiedName); | ||
return source; | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/BlazorWorker.WorkerBackgroundService/BlazorWorker.WorkerBackgroundService.xml
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
57 changes: 57 additions & 0 deletions
57
src/BlazorWorker.WorkerBackgroundService/SerializeLinqExpressionJsonSerializerBase.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using Serialize.Linq.Serializers; | ||
using System; | ||
using System.Linq.Expressions; | ||
|
||
namespace BlazorWorker.WorkerBackgroundService | ||
{ | ||
/// <summary> | ||
/// Base class for adding known types to a serializer using <see cref="Serialize.Linq.Serializers.JsonSerializer"/>. | ||
/// </summary> | ||
public abstract class SerializeLinqExpressionJsonSerializerBase : IExpressionSerializer | ||
{ | ||
private ExpressionSerializer serializer; | ||
|
||
private ExpressionSerializer Serializer | ||
=> this.serializer ?? (this.serializer = GetSerializer()); | ||
|
||
/// <summary> | ||
/// Automatically adds known types as array types. If set to <c>true</c>, sets <see cref="AutoAddKnownTypesAsListTypes"/> to <c>false</c>. | ||
/// </summary> | ||
public bool? AutoAddKnownTypesAsArrayTypes { get; set; } | ||
|
||
/// <summary> | ||
/// Automatically adds known types as list types. If set to <c>true</c>, sets <see cref="AutoAddKnownTypesAsArrayTypes"/> to <c>false</c>. | ||
/// </summary> | ||
public bool? AutoAddKnownTypesAsListTypes { get; set; } | ||
|
||
public abstract Type[] GetKnownTypes(); | ||
|
||
private ExpressionSerializer GetSerializer() | ||
{ | ||
var jsonSerializer = new JsonSerializer(); | ||
foreach (var type in GetKnownTypes()) | ||
{ | ||
jsonSerializer.AddKnownType(type); | ||
} | ||
if (this.AutoAddKnownTypesAsArrayTypes.HasValue) { | ||
jsonSerializer.AutoAddKnownTypesAsArrayTypes = this.AutoAddKnownTypesAsArrayTypes.Value; | ||
} | ||
if (this.AutoAddKnownTypesAsListTypes.HasValue) | ||
{ | ||
jsonSerializer.AutoAddKnownTypesAsListTypes = this.AutoAddKnownTypesAsListTypes.Value; | ||
} | ||
|
||
return new ExpressionSerializer(jsonSerializer); | ||
} | ||
|
||
public Expression Deserialize(string expressionString) | ||
{ | ||
return this.Serializer.DeserializeText(expressionString); | ||
} | ||
|
||
public string Serialize(Expression expression) | ||
{ | ||
return this.Serializer.SerializeText(expression); | ||
} | ||
} | ||
} |
Oops, something went wrong.