{"id":29685944,"url":"https://github.com/teoadal/velo","last_synced_at":"2025-07-23T04:02:42.027Z","repository":{"id":116131974,"uuid":"202733630","full_name":"teoadal/velo","owner":"teoadal","description":"Simple implementations of DI, Mediator (CQRS), Logger, JSON Serializer/Deserializer and Mapper","archived":false,"fork":false,"pushed_at":"2021-04-25T22:00:37.000Z","size":1472,"stargazers_count":7,"open_issues_count":2,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-23T07:43:25.705Z","etag":null,"topics":["cqrs","dependency-injection","deserialization","ioc-container","logging","mediator","serialization"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/teoadal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-16T13:36:09.000Z","updated_at":"2022-07-27T12:07:52.000Z","dependencies_parsed_at":"2023-12-19T13:00:31.221Z","dependency_job_id":null,"html_url":"https://github.com/teoadal/velo","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/teoadal/velo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teoadal%2Fvelo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teoadal%2Fvelo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teoadal%2Fvelo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teoadal%2Fvelo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/teoadal","download_url":"https://codeload.github.com/teoadal/velo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teoadal%2Fvelo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266461338,"owners_count":23932594,"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","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cqrs","dependency-injection","deserialization","ioc-container","logging","mediator","serialization"],"created_at":"2025-07-23T04:01:21.831Z","updated_at":"2025-07-23T04:02:41.956Z","avatar_url":"https://github.com/teoadal.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Velo\n\n[![.NET Core](https://github.com/teoadal/velo/workflows/.NET%20Core/badge.svg?branch=master)](https://github.com/teoadal/velo/actions)\n[![codecov](https://codecov.io/gh/teoadal/velo/branch/master/graph/badge.svg)](https://codecov.io/gh/teoadal/velo)\n[![CodeFactor](https://www.codefactor.io/repository/github/teoadal/velo/badge)](https://www.codefactor.io/repository/github/teoadal/velo)\n[![NuGet](https://img.shields.io/nuget/v/velo.svg)](https://www.nuget.org/packages/velo) \n[![NuGet](https://img.shields.io/nuget/dt/velo.svg)](https://www.nuget.org/packages/velo)\n\n**Do not use in production environment. \nIt's just a training project.**\n\nThe library is performance-oriented package of popular patterns and workflows:\n - CQRS, \n - IoC, \n - serialization/deserialization, \n - logging and mapping\n\n## Install from nuget\n\nInstall Velo with the following command [from nuget](https://www.nuget.org/packages/Velo/):\n\n```ini\nInstall-Package Velo\n```\n\n[For integration](https://github.com/teoadal/velo/wiki/Integration-with-IServiceCollection) with IServiceCollection, install Velo.Extensions.DependencyInjection [from nuget](https://www.nuget.org/packages/Velo.Extensions.DependencyInjection):\n\n```ini\nInstall-Package Velo.Extensions.DependencyInjection\n```\n\n## Emitter (mediator)\n\n```cs\nvar dependencyProvider = new DependencyCollection()\n    .AddEmitter()            // mediator infrastructure\n    .Scan(scanner =\u003e scanner // collect all processors and behaviours\n        .AssemblyOf\u003cIBooRepository\u003e()\n        .RegisterEmitterProcessors())     \n    .BuildProvider();\n\nvar emitter = dependencyProvider.GetRequired\u003cEmitter\u003e();\n\n// ask query (send request)\nBoo boo = await emitter.Ask(new GetBoo { Id = id }); \n\n// execute command\nawait emitter.Execute(new CreateBoo { Id = id }); \n\n// publish notification\nawait emitter.Publish(new Notification { Created = true });\n\n// or ask as struct for reduce memory traffic\nBoo boo = await emitter.Ask\u003cGetBooStruct, Boo\u003e(new GetBooStruct {Id = id}); \n```\n\n### Registration\n\n```cs\nvar dependencyProvider = new DependencyCollection()\n    .AddEmitter()                            // mediator infrastructure\n    .AddCommandBehaviour\u003cMeasureBehaviour\u003e() // add behaviours\n    .AddCommandProcessor\u003cPreProcessor\u003e()\n    .AddCommandProcessor\u003cProcessor\u003e(DependencyLifetime.Scoped) \n    .AddCommandProcessor\u003cPostProcessor\u003e()\n    .AddQueryProcessor\u003cQueryPreProcessor\u003e()\n    .AddQueryProcessor\u003cQueryProcessor\u003e()\n    .AddQueryProcessor\u003cQueryPostProcessor\u003e()\n    .AddNotificationProcessor\u003cOnBooCreated\u003e()\n    .BuildProvider();\n```\n\n### Mediator query (request) benchmark (per 1000 requests)\n\n|               Method |      Mean |    Error |   StdDev | Ratio |  Allocated |\n|--------------------- |----------:|---------:|---------:|------:|-----------:|\n| FullPipeline_MediatR | 805,866.1 ns | 15,881.23 ns | 21,738.41 ns |  1.00 | 1056.07 KB |\n|    **FullPipeline_Velo** | 272,772.9 ns |  5,236.39 ns |  6,430.75 ns |  **0.34** |  **256.07 KB** |\n|                      |              |              |              |       |           |\n|  One_Request_MediatR | 358,579.4 ns |  6,727.49 ns |  7,198.33 ns |  1.00 |  376.07 KB |\n|     **One_Request_Velo** | 132,259.3 ns |  2,136.00 ns |  1,998.02 ns |  **0.37** |  **144.07 KB** |\n\n*FullPipeline - behaviour, pre- and post-processor*.\n\n### Mediator notification benchmark (per 1000 notifications)\n\n|  Method |     Mean |   Error |  StdDev | Ratio | Allocated |\n|-------- |---------:|--------:|--------:|------:|----------:|\n| MediatR | 469.6 us | 9.69 us | 8.59 us |  1.00 |  776 074 B |\n| **Velo** | 107.4 us | 1.63 us | 1.44 us |  **0.23** |      **72 B** |\n\n## Mapper\n\n```cs\nvar compiledMapper = new CompiledMapper\u003cFoo\u003e();\n\nvar source = new Boo\n{\n    Bool = true,\n    Float = 1f,\n    Int = 11\n};\n\nvar foo = compiledMapper.Map(source);\n```\n\n### Benchmark (per 10000 objects)\n\n|     Method |        Mean |     Error |    StdDev | Ratio |  Allocated |\n|----------- |------------:|----------:|----------:|------:|-----------:|\n| AutoMapper |    998.9 us |  10.17 us |   9.51 us |  1.00 |  390.63 KB |\n| **Velo**   |    299.7 us |   3.06 us |   2.86 us |  **0.30** |  **390.63 KB** |\n\n\n## Serialization/Deserialization\n\n### Deserialization\n\n```cs\nvar dependencyProvider = new DependencyCollection()\n    .AddJson() // json converter infrastructure\n    .BuildProvider();\n\nvar converter = dependencyProvider.GetRequired\u003cJConverter\u003e();\nvar deserialized = converter.Deserialize\u003cBoo[]\u003e(json);\n```\n\n### Serialization\n\n```cs\nvar converter = dependencyProvider.GetRequired\u003cJConverter\u003e();\nvar json = converter.Serialize(data);\n```\n\n### Serialization benchmark (per 10000 objects)\n\n|     Method |     Mean |    Error |   StdDev | Ratio | Allocated |\n|----------- |---------:|---------:|---------:|------:|----------:|\n| Newtonsoft | 54.83 ms | 0.567 ms | 0.531 ms |  1.00 |  32.71 MB |\n|   **Velo** | 28.71 ms | 0.431 ms | 0.404 ms |  **0.52** |   **9.87 MB** |\n\n\n### Deserialization benchmark (per 10000 objects)\n\n|     Method |     Mean |    Error |   StdDev | Ratio | Allocated |\n|----------- |---------:|---------:|---------:|------:|----------:|\n| Newtonsoft | 88.41 ms | 1.575 ms | 1.315 ms |  1.00 |  36.85 MB |\n|   **Velo** | 44.28 ms | 0.327 ms | 0.306 ms |  **0.50** |  **19.26 MB** |\n\n\n## Logger \n\n### Configure logger\n\n```cs\nvar dependencyProvider = new DependencyCollection()\n    .AddLogger()\n    .AddDefaultLogEnrichers()         // log level, sender, timestamp\n    .AddLogEnricher\u003cEnricher\u003e()       // add your enricher \n    .AddDefaultConsoleLogWriter()     // primitive log writer\n    .AddLogWriter\u003cLogWriter\u003e()        // add your writer\n    .BuildProvider();\n```\n\n### Use logger\n\n```cs\nvar logger = dependencyProvider.GetRequired\u003cILogger\u003cMyClass\u003e\u003e();\nlogger.Debug(\"My code for handling {instance} executed at {elapsed}\", instance, timer.Elapsed);\n```\n\n### Structured logging\n\n```ini\n[DBG] [MyClass] [2020-02-26T17:07:57] My code for handling { \"Id\": 129, \"Bool\": true, \"Double\": 61, \"Float\": 198, \"Int\": 11, \"IntNullable\": 177, \"String\": \"String64630110-c7c9-4ba2-94c0-4c28dd9cea20\", \"Type\": 0, \"Values\": [36,17,212] } executed at \"0:00:00.0000025\".\n```\n\n### Logger benchmark (per 1000 log events)\n\n|         Method |       Mean |    Error |   StdDev | Ratio |  Allocated |\n|--------------- |-----------:|---------:|---------:|------:|-----------:|\n|   Serilog_EmptySink | 1,110.0 us | 21.86 us | 23.39 us |  1.00 |  851.56 KB |\n|      Nlog_EmptyTarget | 2,355.9 us | 44.31 us | 47.41 us |  2.12 | 1 911.15 KB |\n|      **Velo_EmptyWriter** |   902.4 us | 12.68 us | 11.86 us |  **0.82** |  **219.25 KB** |\n|                |            |          |          |       |            |\n| Serilog_StringWriter | 1,439.7 us | 14.88 us | 12.42 us |  1.00 |  976.25 KB |\n|    Nlog_StringWriter | 2,061.0 us | 26.41 us | 24.70 us |  1.43 | 1 648.44 KB |\n|    **Velo_StringWriter** | 1,225.1 us | 11.20 us |  9.93 us |  **0.85** |  **219.56 KB** |\n\n## Dependency Injection\n\n### Create dependency provider\n\n```cs\nvar dependencyProvider = new DependencyCollection()\n    .AddScoped\u003cSomethingController\u003e()\n    .AddSingleton\u003cIFooService, FooService\u003e()\n    .AddSingleton(typof(IMapper\u003c\u003e), typeof(CompiledMapper\u003c\u003e))\n    .AddSingleton\u003cIConfiguration\u003e(ctx =\u003e new Configuration())\n    .AddTransient\u003cISession, Session\u003e()\n    .BuildProvider();\n```\n\n### Use an assembly scanner to find generic interface implementations\n\n```cs\nvar dependencyProvider = new DependencyCollection()\n    .Scan(scanner =\u003e scanner\n        .AssemblyOf\u003cIRepository\u003e()\n        .RegisterAsSingleton(typeof(IRepository\u003c\u003e)))\n    .BuildProvider();\n```\n\n### Resolve dependency\n\n```cs\n// possible null or empty\nvar repositoryArray = dependencyProvider.Get\u003cIRepository[]\u003e();\n\n// not null or exception\nvar converterSingleton = dependencyProvider.GetRequired\u003cJConverter\u003e();\n\n// registered as transient\nvar session = dependencyProvider.Get\u003cISession\u003e();\nvar otherSession = dependencyProvider.Get\u003cISession\u003e();\n```\n\n### Use scope\n\n```cs\nusing (var scope = dependencyProvider.StartScope())\n{\n    var controller = scope.Get\u003cSomethingController\u003e();\n}\n```\n\n### Benchmarks\n\n#### Create dependency container benchmark\n\n|       Method |       Mean |     Error |    StdDev |  Ratio | Allocated |\n|------------- |-----------:|----------:|----------:|-------:|----------:|\n|      Autofac |  42.710 us | 0.4666 us | 0.4136 us |  18.28 |   38.9 KB |\n|       Castle | 245.270 us | 2.0700 us | 1.9363 us | 105.06 |  91.71 KB |\n|         Core |   2.338 us | 0.0254 us | 0.0212 us |   1.00 |   5.54 KB |\n|  LightInject |  13.078 us | 0.0809 us | 0.0757 us |   5.60 |  37.45 KB |\n| SimpleInject | 401.719 us | 3.0091 us | 2.6675 us | 171.80 |   42.7 KB |\n|     **Velo** |   1.739 us | 0.0200 us | 0.0178 us |   **0.74** |   **3.04 KB** |\n|        Unity |  15.096 us | 0.2847 us | 0.2796 us |   6.44 |  22.41 KB |\n\n\n#### Resolve singleton service from container\n\n|       Method |        Mean |     Error |    StdDev | Ratio | Allocated |\n|------------- |------------:|----------:|----------:|------:|----------:|\n|      Autofac |   762.68 ns | 15.218 ns | 25.841 ns |  3.83 |   1 656 B |\n|       Castle |   536.30 ns |  5.416 ns |  5.066 ns |  2.71 |   1 200 B |\n|         Core |   198.20 ns |  2.320 ns |  2.057 ns |  1.00 |     216 B |\n|  LightInject |    85.05 ns |  0.624 ns |  0.584 ns |  0.43 |     216 B |\n| SimpleInject |   128.19 ns |  0.942 ns |  0.881 ns |  0.65 |     216 B |\n|     **Velo** |   195.92 ns |  2.089 ns |  1.954 ns |  **0.99** |     **216 B** |\n|        Unity |   455.58 ns |  3.135 ns |  2.932 ns |  2.30 |     552 B |\n\n\n## LocalVector (small collection on stack)\n\nRef struct to collect values on stack. This collection allows you to reduce memory consumption. Also, it allows to work with several variables as a collection without extra costs. Read about LocalList [here](https://github.com/teoadal/velo/wiki/LocalList-(collection-on-stack)).\n\n### Usage\n\n```cs\nvar vector = new LocalVector\u003cBoo\u003e();\nvector.Add(new Boo()); // add less 10 elements for performance effect\n```\n\n### Linq-like via ref struct enumerators\n\n```cs\nvar outer = new LocalVector\u003cBoo\u003e(_items);\nvar inner = new LocalVector\u003cBoo\u003e(_reversItems);\n\nvar counter = 0;\nforeach (var number in outer\n    .Join(inner, o =\u003e o, i =\u003e i, (o, i) =\u003e i) \n    .Where((b, threshold) =\u003e b.Int \u003e threshold, _threshold) // use an argument to avoid closure\n    .Select((b, modifier) =\u003e b.Id * modifier, _modifier)\n    .OrderBy(id =\u003e id))\n{\n    counter += number;\n}\n\nreturn counter;\n```\n\n### Local vector benchmarks (collection with 10 elements)\n\n|                    Method |         Mean |      Error |     StdDev | Ratio | Allocated |\n|-------------------------- |-------------:|-----------:|-----------:|------:|----------:|\n|                  List_Add |    12.926 ns |  0.1850 ns |  0.1731 ns |  1.00 |      33 B |\n|           LocalVector_Add |     5.502 ns |  0.0313 ns |  0.0244 ns |  0.42 |         - |\n|                  Span_Add |     3.852 ns |  0.0196 ns |  0.0153 ns |  0.30 |      10 B |\n|                           |              |            |            |       |           |\n|            List_Iteration |     9.937 ns |  0.2311 ns |  0.2923 ns |  1.00 |      14 B |\n|     LocalVector_Iteration |     9.701 ns |  0.0504 ns |  0.0472 ns |  0.97 |         - |\n|            Span_Iteration |     8.521 ns |  0.0899 ns |  0.0797 ns |  0.85 |      10 B |\n|                           |              |            |            |       |           |\n|              List_GroupBy |    71.959 ns |  0.5214 ns |  0.4877 ns |  1.00 |     102 B |\n|       LocalVector_GroupBy |    83.630 ns |  0.2430 ns |  0.2273 ns |  1.16 |         - |\n|                           |              |            |            |       |           |\n|                 List_Join |   111.531 ns |  0.3870 ns |  0.3232 ns |  1.00 |     167 B |\n|          LocalVector_Join |   117.925 ns |  0.3964 ns |  0.3708 ns |  1.06 |         - |\n|                           |              |            |            |       |           |\n|             List_ManyLinq |   238.136 ns |  1.0246 ns |  0.9584 ns |  1.00 |     366 B |\n|      LocalVector_ManyLinq |   425.516 ns |  1.3847 ns |  1.2952 ns |  1.79 |         - |\n|                           |              |            |            |       |           |\n|               List_Remove |    31.604 ns |  0.2091 ns |  0.1956 ns |  1.00 |      14 B |\n|        LocalVector_Remove |    52.423 ns |  0.3658 ns |  0.3422 ns |  1.66 |         - |\n|                           |              |            |            |       |           |\n|               List_Select |    22.865 ns |  0.0749 ns |  0.0664 ns |  1.00 |      21 B |\n|        LocalVector_Select |    17.396 ns |  0.0883 ns |  0.0737 ns |  0.76 |         - |\n|                           |              |            |            |       |           |\n|              List_ToArray |     8.174 ns |  0.0553 ns |  0.0461 ns |  1.00 |      24 B |\n|       LocalVector_ToArray |    11.211 ns |  0.0623 ns |  0.0583 ns |  1.37 |      10 B |\n|              Span_ToArray |     2.284 ns |  0.0195 ns |  0.0182 ns |  0.28 |      10 B |\n|                           |              |            |            |       |           |\n|                List_Where |    22.720 ns |  0.0935 ns |  0.0874 ns |  1.00 |      21 B |\n|              List_FindAll |    20.528 ns |  0.1968 ns |  0.1744 ns |  0.90 |      31 B |\n|         LocalVector_Where |    18.991 ns |  0.0860 ns |  0.0805 ns |  0.84 |         - |\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteoadal%2Fvelo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fteoadal%2Fvelo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteoadal%2Fvelo/lists"}