{"id":21962418,"url":"https://github.com/megafetis/conveyr","last_synced_at":"2025-04-23T21:22:19.207Z","repository":{"id":51296409,"uuid":"266830459","full_name":"megafetis/ConveyR","owner":"megafetis","description":"The library takes code reuse to a new level. Define one handler for interface and use it for many classes","archived":false,"fork":false,"pushed_at":"2022-06-12T05:24:17.000Z","size":147,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-15T07:42:36.680Z","etag":null,"topics":["conveyor","conveyor-handling","dependencyinjection","handlers","processing"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/megafetis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-25T16:40:58.000Z","updated_at":"2023-09-08T18:07:57.000Z","dependencies_parsed_at":"2022-09-05T22:50:50.152Z","dependency_job_id":null,"html_url":"https://github.com/megafetis/ConveyR","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/megafetis%2FConveyR","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/megafetis%2FConveyR/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/megafetis%2FConveyR/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/megafetis%2FConveyR/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/megafetis","download_url":"https://codeload.github.com/megafetis/ConveyR/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250515326,"owners_count":21443371,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["conveyor","conveyor-handling","dependencyinjection","handlers","processing"],"created_at":"2024-11-29T10:39:47.098Z","updated_at":"2025-04-23T21:22:19.191Z","avatar_url":"https://github.com/megafetis.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ConveyR - Handling of business objects by shared interfaces\n=======\n[![NuGet](https://img.shields.io/nuget/dt/ConveyR.svg)](https://www.nuget.org/packages/ConveyR/) \n[![NuGet](https://img.shields.io/nuget/vpre/ConveyR.svg)](https://www.nuget.org/packages/ConveyR/)\n\nSimple implementation of conveyor handling  in .NET.\nThe library takes code reuse to a new level.\nIn-process object handling with no dependencies.\n\n## Conveyor handling of business objects:\n\nWrite your `AbstractProcessHandler\u003cSomeContext,ISomeInterface,ISomePayload\u003e` business-logic handlers for every business interfaces. Optionally you can pass interfaces for payload too.\nRun conveyor to handle each business object of several classes, if they have a common interfaces.\n\n### Installing ConveyR\n\nYou should install [ConveyR with NuGet](https://www.nuget.org/packages/ConveyR):\n\n    Install-Package ConveyR\n    \nOr via the .NET Core command line interface:\n\n    dotnet add package ConveyR\n\nUse this library to define handlers once and use them to handle different objects with shared interfaces or shared base classes.\nLib contains:\n* `IConveyor` interface to use as entry point to handle\n* `IProcessHandler` and `AbstractProcessHandler` to define handlers\n* delegate `ServiceFactory` for connecting with any DI containers. [Extensions for Microsoft.DependencyInjection](https://www.nuget.org/packages/ConveyR.Extensions.Microsoft.DependencyInjection/)\n\n### Common usage (Example):\n\n### Define your domain classes and interfaces:\n\n```cs \npublic class EntityClass1: IEntity, IHasNaming, IHasDescription\n{\n    public string Id {get; set;}\n    public string Name {get; set;}\n    public string Description {get; set;}\n}\n\npublic class EntityClass2: IEntity, IHasNaming\n{\n    public string Id {get; set;}\n    public string Name {get; set;}\n}\n\n```\n\n```cs\n\ninterface IEntity\n{\n    string Id {get; set;}\n}\n\ninterface IHasNaming\n{\n    string Name {get; set;}\n}\n\ninterface IHasDescription\n{\n    string Description {get; set;}\n}\n```\n\n### Define DTO domain model classes:\n\n```cs\n\ninterface IHasNamingPayload\n{\n    string Name {get; set;}\n}\n\ninterface IHasDescriptionPayload\n{\n    string Description {get; set;}\n}\n\nclass EditEntityModel1: IHasNamingPayload,IHasDescriptionPayload\n{\n    public string Name {get; set;}\n    public string Description {get; set;}\n}\n\n```\n\n### Define Handlers from ``AbstractProcessHandler\u003c,\u003e`` or ``IProcessHandler\u003c,\u003e``:\n\n```cs\n\n// IEntity handler without payload\nclass GenerateIdHandler:AbstractProcessHandler\u003cMyStore, IEntity\u003e\n{\n    protected override Task Process(TestEntitiesStore context, IEntity entity, CancellationToken cancellationToken = default)\n    {\n        if (string.IsNullOrEmpty(entity.Id))\n        {\n            entity.Id = Guid.NewGuid().ToString(\"N\");\n            // You have access to context object\n            context._someUnitOfWork.SomeMethod(entity);\n        }\n\n        \n\n        return Task.CompletedTask;\n    }\n}\n\n// IHasNaming handler with payload\nclass ChangeNameHandler:AbstractProcessHandler\u003cMyStore, IHasNaming,IHasNamingPayload\u003e\n{\n    protected override Task Process(TestEntitiesStore context, IHasNaming entity, IHasNamingPayload payload,CancellationToken cancellationToken = default)\n    {\n        if(payload.Name==null)\n            throw new ArgumentNullException(\"Name\",\"Entity name must be named\");\n        entity.Name = payload.Name;\n        return Task.CompletedTask;\n    }\n}\n\n// IHasDescription handler with payload\nclass ChangeDescriptionHandler: AbstractProcessHandler\u003cMyStore, IHasDescription,IHasDescriptionPayload\u003e\n{\n    protected override Task Process(TestEntitiesStore context, IHasDescription entity, IHasDescriptionPayload payload, CancellationToken cancellationToken = default)\n    {\n        entity.Description = payload.Description;\n        return Task.CompletedTask;\n    }\n}\n\n\n```\n### Start processing in your store or controller:\n\n``MyStore `` is some class, where may be started handling.\n\n\n```cs \nclass MyStore\n{\n    private readonly IConveyor _conveyor;\n    public readonly ISomeUnitOfWork _someUnitOfWork;\n    public MyStore(IConveyor conveyor)\n    {\n        _conveyor = conveyor;\n        _someUnitOfWork = new SomeUnitOfWork();\n    }\n\n    public async Task AddOrSaveEntity(IEntity entity,object payload = null)\n    {\n        await _conveyor.Process(this,entity,payload); // the conveyor will find all required handlers and apply them\n    }\n}\n\n//...\n\nvar store = new MyStore(_conveyor);\nvar entity = new EntityClass1();\nvar entity2 = new EntityClass1();\nvar payload = new EditEntityModel1()\n{\n    Name = \"Name 1\",\n    Description = \"Description 1\",\n}\n\nstore.AddOrSaveEntity(entity,payload);\nstore.AddOrSaveEntity(entity2,payload);\n\n```\n\nTo register handlers you can use DI container:\n\n```cs\n\nvar services = new ServiceCollection();\nservices.AddConveyR();\nvar provider = services.BuildServiceProvider();\n\n```\n...\n\n```cs \n\nvar conveyor = _serviceProvider.GetService\u003cIConveyor\u003e();\n// ...\n\n```\nor implement some simple ``ServiceFactory``\n\n```cs\npublic class SimpleServiceFactory\n{\n    public SimpleServiceFactory(params Type[] handlerTypes)\n    {\n        ServiceFactoryExtensions.SetHandlerTypes(handlerTypes);\n    }\n    public IEnumerable\u003cobject\u003e GetServices(Type contextType, Type entityType, Type payloadType = null, string processCase=null)\n    {\n        var types = ServiceFactoryExtensions.GetProcessServiceTypes(contextType, entityType, payloadType, processCase);\n\n        if(!types.Any())\n            yield break;\n\n        foreach (var type in types)\n        {\n            var h = Activator.CreateInstance(type);\n            yield return h;\n        }\n    }\n}\n\nvar factory = new SimpleServiceFactory(typeof(ChangeNameHandler), typeof(ChangeDescriptionHandler),typeof(GenerateIdHandler));\n\nvar conveyor = new Conveyor(factory.GetServices);\n\nvar myStore = new MyStore(conveyor);\n\n```\nWith DI Microsoft.DependencyInjection:\n\n\n\n#### You can lable handlers to split them into groups and manage ordering of handling:\n\n```cs\n\n[ProcessConfig(Order=1,Group=\"aftercommit\")]\nclass WriteToLogHandler:AbstractProcessHandler\u003cMyStore, IEntity\u003e\n{\n    protected override Task Process(TestEntitiesStore context, IEntity entity, CancellationToken cancellationToken = default)\n    {\n        Console.Writeline($\"{entity.Id} stored\");\n        return Task.CompletedTask;\n    }\n}\n\n//...\n\nclass MyStore\n{\n    private readonly IConveyor _conveyor;\n    public readonly ISomeUnitOfWork _someUnitOfWork;\n    public MyStore(IConveyor conveyor)\n    {\n        _conveyor = conveyor;\n        _someUnitOfWork = new SomeUnitOfWork();\n    }\n\n    public async Task AddOrSaveEntity(IEntity entity,object payload = null)\n    {\n        await _conveyor.Process(this,entity,payload); // the conveyor will find all required handlers and apply them\n    }\n\n    public async Task AfterSaveEntity(IEntity entity,object payload = null)\n    {\n        await _conveyor.Process(this,entity,payload,\"aftercommit\");\n    }\n    \n}\n\n```\n\nPlease give a star if the library is useful for you :smiley:\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmegafetis%2Fconveyr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmegafetis%2Fconveyr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmegafetis%2Fconveyr/lists"}