Skip to content

Instantly share code, notes, and snippets.

@NDiiong
Last active September 12, 2020 10:09
Show Gist options
  • Save NDiiong/6478af700979c3fb2faa06252da354ae to your computer and use it in GitHub Desktop.
Save NDiiong/6478af700979c3fb2faa06252da354ae to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace DomainServices
{
public class DataBuilder<TIn, TOut> where TIn : class where TOut : class, new()
{
private readonly Dictionary<string, IDataPartBuilder<TIn, TOut>> _dataPartBuilders;
private ILogger _logger;
private DataContext Context { get; set; }
public DataBuilder()
{
_dataPartBuilders = new Dictionary<string, IDataPartBuilder<TIn, TOut>>(StringComparer.OrdinalIgnoreCase);
}
public IDataPartBuilder<TIn, TOut> this[string key] => _dataPartBuilders[key];
public DataBuilder(DataContext dataContext) : this()
{
Context = dataContext;
}
public DataBuilder<TIn, TOut> AddIntegrateLog(ILogger logger)
{
_logger = logger;
return this;
}
public DataBuilder<TIn, TOut> AddConvertContext(DataContext dataContext)
{
Context = dataContext;
return this;
}
public DataBuilder<TIn, TOut> AddPartBuilder(IDataPartBuilder<TIn, TOut> builderPart)
{
_dataPartBuilders.Add(Guid.NewGuid().ToString(), builderPart);
return this;
}
public DataBuilder<TIn, TOut> AddPartBuilder<TPart>() where TPart : IDataPartBuilder<TIn, TOut>, new()
{
var builderPart = Activator.CreateInstance<TPart>();
_dataPartBuilders.Add(Guid.NewGuid().ToString(), builderPart);
return this;
}
public DataBuilder<TIn, TOut> AddPartBuilder<TPart>(string key) where TPart : IDataPartBuilder<TIn, TOut>, new()
{
var builderPart = Activator.CreateInstance<TPart>();
_dataPartBuilders.Add(key, builderPart);
return this;
}
public DataBuilder<TIn, TOut> AddPartBuilder(IDictionary<string, IDataPartBuilder<TIn, TOut>> builderParts)
{
foreach (var item in builderParts)
{
_dataPartBuilders.Add(item.Key, item.Value);
}
return this;
}
public DataBuilder<TIn, TOut> AddRangePartBuilder(IEnumerable<IDataPartBuilder<TIn, TOut>> builderParts)
{
foreach (var item in builderParts)
{
AddPartBuilder(item);
}
return this;
}
public virtual async Task<TOut> BuildAsync(TIn @input, CancellationToken cancellationToken = default)
{
var resultData = Activator.CreateInstance<TOut>();
foreach (var part in _dataPartBuilders)
{
resultData = await part.Value
.InjectContext(Context)
.BuildAsync(@input, resultData)
.ConfigureAwait(false);
}
return await Task.FromResult(resultData).ConfigureAwait(false);
}
public virtual async Task<TOut> BuildAsync(TIn @input, TOut @output, string key, CancellationToken cancellationToken = default)
{
if (!_dataPartBuilders.ContainsKey(key))
throw new KeyNotFoundException($"Key '{key}' does not exists in map.");
var partBuilder = _dataPartBuilders[key];
await partBuilder
.InjectContext(Context)
.BuildAsync(@input, @output)
.ConfigureAwait(false);
return await Task.FromResult(@output).ConfigureAwait(false);
}
}
}
public abstract class DataContext
{
}
public interface IDataPartBuilder<TIn, TOut> where TIn : class where TOut : class
{
IDataPartBuilder<TIn, TOut> InjectContext(DataContext transactionContext);
Task<TOut> BuildAsync(TIn input, TOut output);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment