https://github.com/megafetis/conveyr
The library takes code reuse to a new level. Define one handler for interface and use it for many classes
https://github.com/megafetis/conveyr
conveyor conveyor-handling dependencyinjection handlers processing
Last synced: about 1 year ago
JSON representation
The library takes code reuse to a new level. Define one handler for interface and use it for many classes
- Host: GitHub
- URL: https://github.com/megafetis/conveyr
- Owner: megafetis
- License: apache-2.0
- Created: 2020-05-25T16:40:58.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2022-06-12T05:24:17.000Z (almost 4 years ago)
- Last Synced: 2025-04-15T07:42:36.680Z (about 1 year ago)
- Topics: conveyor, conveyor-handling, dependencyinjection, handlers, processing
- Language: C#
- Homepage:
- Size: 144 KB
- Stars: 6
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# ConveyR - Handling of business objects by shared interfaces
=======
[](https://www.nuget.org/packages/ConveyR/)
[](https://www.nuget.org/packages/ConveyR/)
Simple implementation of conveyor handling in .NET.
The library takes code reuse to a new level.
In-process object handling with no dependencies.
## Conveyor handling of business objects:
Write your `AbstractProcessHandler` business-logic handlers for every business interfaces. Optionally you can pass interfaces for payload too.
Run conveyor to handle each business object of several classes, if they have a common interfaces.
### Installing ConveyR
You should install [ConveyR with NuGet](https://www.nuget.org/packages/ConveyR):
Install-Package ConveyR
Or via the .NET Core command line interface:
dotnet add package ConveyR
Use this library to define handlers once and use them to handle different objects with shared interfaces or shared base classes.
Lib contains:
* `IConveyor` interface to use as entry point to handle
* `IProcessHandler` and `AbstractProcessHandler` to define handlers
* delegate `ServiceFactory` for connecting with any DI containers. [Extensions for Microsoft.DependencyInjection](https://www.nuget.org/packages/ConveyR.Extensions.Microsoft.DependencyInjection/)
### Common usage (Example):
### Define your domain classes and interfaces:
```cs
public class EntityClass1: IEntity, IHasNaming, IHasDescription
{
public string Id {get; set;}
public string Name {get; set;}
public string Description {get; set;}
}
public class EntityClass2: IEntity, IHasNaming
{
public string Id {get; set;}
public string Name {get; set;}
}
```
```cs
interface IEntity
{
string Id {get; set;}
}
interface IHasNaming
{
string Name {get; set;}
}
interface IHasDescription
{
string Description {get; set;}
}
```
### Define DTO domain model classes:
```cs
interface IHasNamingPayload
{
string Name {get; set;}
}
interface IHasDescriptionPayload
{
string Description {get; set;}
}
class EditEntityModel1: IHasNamingPayload,IHasDescriptionPayload
{
public string Name {get; set;}
public string Description {get; set;}
}
```
### Define Handlers from ``AbstractProcessHandler<,>`` or ``IProcessHandler<,>``:
```cs
// IEntity handler without payload
class GenerateIdHandler:AbstractProcessHandler
{
protected override Task Process(TestEntitiesStore context, IEntity entity, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(entity.Id))
{
entity.Id = Guid.NewGuid().ToString("N");
// You have access to context object
context._someUnitOfWork.SomeMethod(entity);
}
return Task.CompletedTask;
}
}
// IHasNaming handler with payload
class ChangeNameHandler:AbstractProcessHandler
{
protected override Task Process(TestEntitiesStore context, IHasNaming entity, IHasNamingPayload payload,CancellationToken cancellationToken = default)
{
if(payload.Name==null)
throw new ArgumentNullException("Name","Entity name must be named");
entity.Name = payload.Name;
return Task.CompletedTask;
}
}
// IHasDescription handler with payload
class ChangeDescriptionHandler: AbstractProcessHandler
{
protected override Task Process(TestEntitiesStore context, IHasDescription entity, IHasDescriptionPayload payload, CancellationToken cancellationToken = default)
{
entity.Description = payload.Description;
return Task.CompletedTask;
}
}
```
### Start processing in your store or controller:
``MyStore `` is some class, where may be started handling.
```cs
class MyStore
{
private readonly IConveyor _conveyor;
public readonly ISomeUnitOfWork _someUnitOfWork;
public MyStore(IConveyor conveyor)
{
_conveyor = conveyor;
_someUnitOfWork = new SomeUnitOfWork();
}
public async Task AddOrSaveEntity(IEntity entity,object payload = null)
{
await _conveyor.Process(this,entity,payload); // the conveyor will find all required handlers and apply them
}
}
//...
var store = new MyStore(_conveyor);
var entity = new EntityClass1();
var entity2 = new EntityClass1();
var payload = new EditEntityModel1()
{
Name = "Name 1",
Description = "Description 1",
}
store.AddOrSaveEntity(entity,payload);
store.AddOrSaveEntity(entity2,payload);
```
To register handlers you can use DI container:
```cs
var services = new ServiceCollection();
services.AddConveyR();
var provider = services.BuildServiceProvider();
```
...
```cs
var conveyor = _serviceProvider.GetService();
// ...
```
or implement some simple ``ServiceFactory``
```cs
public class SimpleServiceFactory
{
public SimpleServiceFactory(params Type[] handlerTypes)
{
ServiceFactoryExtensions.SetHandlerTypes(handlerTypes);
}
public IEnumerable GetServices(Type contextType, Type entityType, Type payloadType = null, string processCase=null)
{
var types = ServiceFactoryExtensions.GetProcessServiceTypes(contextType, entityType, payloadType, processCase);
if(!types.Any())
yield break;
foreach (var type in types)
{
var h = Activator.CreateInstance(type);
yield return h;
}
}
}
var factory = new SimpleServiceFactory(typeof(ChangeNameHandler), typeof(ChangeDescriptionHandler),typeof(GenerateIdHandler));
var conveyor = new Conveyor(factory.GetServices);
var myStore = new MyStore(conveyor);
```
With DI Microsoft.DependencyInjection:
#### You can lable handlers to split them into groups and manage ordering of handling:
```cs
[ProcessConfig(Order=1,Group="aftercommit")]
class WriteToLogHandler:AbstractProcessHandler
{
protected override Task Process(TestEntitiesStore context, IEntity entity, CancellationToken cancellationToken = default)
{
Console.Writeline($"{entity.Id} stored");
return Task.CompletedTask;
}
}
//...
class MyStore
{
private readonly IConveyor _conveyor;
public readonly ISomeUnitOfWork _someUnitOfWork;
public MyStore(IConveyor conveyor)
{
_conveyor = conveyor;
_someUnitOfWork = new SomeUnitOfWork();
}
public async Task AddOrSaveEntity(IEntity entity,object payload = null)
{
await _conveyor.Process(this,entity,payload); // the conveyor will find all required handlers and apply them
}
public async Task AfterSaveEntity(IEntity entity,object payload = null)
{
await _conveyor.Process(this,entity,payload,"aftercommit");
}
}
```
Please give a star if the library is useful for you :smiley: