You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Connected.Common/Common.Numbering/NumberingOps.cs

138 lines
3.0 KiB

using Connected.Entities;
using Connected.Entities.Storage;
using Connected.Interop;
using Connected.Middleware;
using Connected.ServiceModel;
using Connected.Services;
namespace Common.Numbering;
internal sealed class NumberingOps
{
public sealed class Calculate : ServiceFunction<NumberingCalculateArgs, string>
{
public Calculate(IMiddlewareService middleware)
{
Middleware = middleware;
}
private IMiddlewareService Middleware { get; }
protected override async Task<string?> OnInvoke()
{
foreach (var middleware in await Middleware.Query<INumberingProvider>())
{
if (await middleware.Invoke(Arguments) is string result && !string.IsNullOrEmpty(result))
return result;
}
return null;
}
}
public sealed class NextValue : ServiceFunction<NumberingCalculateArgs, string>
{
public NextValue(IStorageProvider storage, INumberingService numbering)
{
Storage = storage;
Numbering = numbering;
}
private IStorageProvider Storage { get; }
private INumberingService Numbering { get; }
protected override async Task<string?> OnInvoke()
{
var result = await Prepare();
await Storage.Open<Numbering>().Update(result, Arguments,
async () =>
{
result = await Prepare();
return result;
},
async (f) =>
{
await Task.CompletedTask;
return f;
});
return result.Value;
}
private async Task<Numbering> Prepare()
{
var current = await Numbering.Select(Arguments.AsArguments<NumberingSelectArgs>());
if (current is null)
{
var id = await TryInsert();
if (id == 0)
current = await Numbering.Select(Arguments.AsArguments<NumberingSelectArgs>());
else
current = await Numbering.Select(id);
}
if (current is null)
throw new NullReferenceException(nameof(INumbering));
var newValue = string.Empty;
if (TypeConversion.TryConvert(current.Value, out long existingValue))
newValue = existingValue++.ToString();
else
newValue = current.Value;
return (Numbering)current with { Value = newValue };
}
private async Task<int> TryInsert()
{
try
{
return (await Storage.Open<Numbering>().Update(Arguments.AsEntity<Numbering>(State.New))).Id;
}
catch
{
return 0;
}
}
}
public sealed class SelectByEntity : ServiceFunction<NumberingSelectArgs, INumbering>
{
public SelectByEntity(IStorageProvider storage)
{
Storage = storage;
}
private IStorageProvider Storage { get; }
protected override async Task<INumbering?> OnInvoke()
{
return await (from e in Storage.Open<Numbering>()
where string.Equals(e.Entity, Arguments.Entity, StringComparison.OrdinalIgnoreCase)
select e).AsEntity();
}
}
public sealed class Select : ServiceFunction<PrimaryKeyArgs<int>, INumbering>
{
public Select(IStorageProvider storage)
{
Storage = storage;
}
private IStorageProvider Storage { get; }
protected override async Task<INumbering?> OnInvoke()
{
return await (from e in Storage.Open<Numbering>()
where e.Id == Arguments.Id
select e).AsEntity();
}
}
}