{"id":19100665,"url":"https://github.com/thomhurst/AllOf","last_synced_at":"2025-04-18T18:30:44.627Z","repository":{"id":60143888,"uuid":"541249903","full_name":"thomhurst/AllOf","owner":"thomhurst","description":"Use Publish/Subscribe type classes without creating Publisher classes","archived":false,"fork":false,"pushed_at":"2022-10-20T12:19:52.000Z","size":103,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2023-03-02T12:45:53.324Z","etag":null,"topics":[],"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/thomhurst.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-09-25T17:17:36.000Z","updated_at":"2022-09-29T02:51:57.000Z","dependencies_parsed_at":"2023-01-20T15:46:47.488Z","dependency_job_id":null,"html_url":"https://github.com/thomhurst/AllOf","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomhurst%2FAllOf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomhurst%2FAllOf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomhurst%2FAllOf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomhurst%2FAllOf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thomhurst","download_url":"https://codeload.github.com/thomhurst/AllOf/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223783097,"owners_count":17201904,"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":[],"created_at":"2024-11-09T03:52:56.738Z","updated_at":"2025-04-18T18:30:44.620Z","avatar_url":"https://github.com/thomhurst.png","language":"C#","funding_links":["https://www.buymeacoffee.com/tomhurst"],"categories":["others"],"sub_categories":[],"readme":"# AllOf\n\nUse `Producer/Consumer` type classes without creating Producer classes just to call Consumer classes.\n\n- Create your implementations\n- Register them under the same interface\n- Inject in AllOf\u003cInterface\u003e and use that to send a 'Publish' command.\n\n## Support\n\nIf you like this library, consider buying me a coffee.\n\n\u003ca href=\"https://www.buymeacoffee.com/tomhurst\" target=\"_blank\"\u003e\u003cimg src=\"https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png\" alt=\"Buy Me A Coffee\" style=\"height: auto !important;width: auto !important;\" \u003e\u003c/a\u003e\n    \n## Example\nReduce:\n    \n```csharp\npublic class MyImplementation1 : IMyInterface { ... }\npublic class MyImplementation2 : IMyInterface { ... }\npublic class MyImplementation3 : IMyInterface { ... }\n    \npublic interface IMyPublisher\n{\n    void PublishSomething();\n    Task PublishSomethingAsync();\n}\n\npublic class MyPublisher : IMyPublisher \n{\n    private readonly IEnumerable\u003cIMyInterface\u003e _myInterfaces;\n    \n    public MyPublisher(IEnumerable\u003cIMyInterface\u003e myInterfaces)\n    {\n        _myInterfaces = myInterfaces;\n    }\n    \n    public void PublishSomething()\n    {\n        foreach(var myInterface in _myInterfaces)\n        {\n            myInterface.DoSomething();\n        }\n    }\n    \n    public async Task PublishSomethingAsync()\n    {\n        var tasks = _myInterfaces.Select(myInterface =\u003e myInterface.DoSomethingAsync());\n        await Task.WhenAll(tasks);\n    }\n}\n    \npublic class MyWorker\n{\n  private readonly IMyPublisher _myPublisher;\n  \n  public MyWorker(IMyPublisher _myPublisher)\n  {\n      _myPublisher = myPublisher;\n  }\n    \n  public async Task DoSomething()\n  {\n        ...\n        _myPublisher.PublishSomething();\n        await _myPublisher.PublishSomethingAsync();\n  }\n}   \n```   \n    \nTo\n    \n```csharp\npublic class MyImplementation1 : IMyInterface { ... }\npublic class MyImplementation2 : IMyInterface { ... }\npublic class MyImplementation3 : IMyInterface { ... }\n    \npublic class MyWorker\n{\n  private readonly AllOf\u003cIMyInterface\u003e _myInterfaces;\n  \n  public MyWorker(AllOf\u003cIMyInterface\u003e myInterfaces)\n  {\n      _myInterfaces = myInterfaces;\n  }\n    \n  public async Task DoSomething()\n  {\n        ...\n        _myInterfaces.OnEach().DoSomething();\n        await _myInterfaces.OnEach().DoSomethingAsync();\n  }\n}\n```\n    \nIt may not seem like much, but it eliminates an entire class. \nIt also means you don't need to handle the looping and Task (if async) management on these methods.\n    \n## Usage\n\n1.  Register multiple implementations of your interfaces(s) in your ServiceCollection\n\n```csharp\nservices.AddSingleton\u003cIMyInterface, MyImplementation1\u003e()\n    .AddScoped\u003cIMyInterface, MyImplementation2\u003e()\n    .AddTransient\u003cIMyInterface, MyImplementation3\u003e();\n```\n\n2.  Call `AddAllOfs()` on your ServiceCollection\n\n```csharp\n        services.AddAllOfs()\n```\n\n3.  Inject `AllOf\u003cT\u003e` into your class\n\n```csharp\npublic class MyWorker\n{\n  private readonly AllOf\u003cIMyInterface\u003e _myInterfaces;\n  \n  public MyWorker(AllOf\u003cIMyInterface\u003e myInterfaces)\n  {\n      _myInterfaces = myInterfaces;\n  }\n}\n```\n\n4.  Call `AllOf.OnEach().SomeMethod()` and it'll call the same method in all of the different implementations. This handles asynchronous Tasks as well as synchronous methods, so no loop or Task handling for you to implement.\n\n```csharp\n_myInterfaces.OnEach().DoSomething();\nawait _myInterface.OnEach().DoSomethingElseAsync();\n```\n\nThe above will essentially do:\n\n```csharp\nMyImplementation1.DoSomething();\nMyImplementation2.DoSomething();\nMyImplementation3.DoSomething();\n\nawait Task.WhenAll(\n  MyImplementation1.DoSomethingElseAsync(),\n  MyImplementation2.DoSomethingElseAsync(),\n  MyImplementation3.DoSomethingElseAsync()\n);\n```\n\n # AllOf\u003c\u003e\n    \n`AllOf\u003c\u003e` is an interface so can be easily mocked. As well as `OnEach()`, it holds an `Items` property which is an `IEnumerable\u003cT\u003e` if you need to access your enumerable of implementations.\n\n## Custom Naming\n    \nIf you want to change the naming, create a wrapper class around it and register it in the DI.\nE.g.\n\n```csharp\npublic interface PublisherOf\u003cout T\u003e\n{\n    T ForEachSubscriber();\n}\n\npublic class PublisherOfImpl\u003cT\u003e : PublisherOf\u003cT\u003e\n{\n    private readonly AllOf\u003cT\u003e _allOf;\n\n    public PublisherOfImpl(AllOf\u003cT\u003e allOf)\n    {\n        _allOf = allOf;\n    }\n    \n    public T ForEachSubscriber()\n    {\n        return _allOf.OnEach();\n    }\n}\n```\n\nin Startup do\n```csharp\nservices.AddTransient(typeof(PublisherOf\u003c\u003e), typeof(PublisherOfImpl\u003c\u003e))\n```\n\nAnd then you can inject this type into your classes, if that reads better for your codebase.\n\n```csharp\npublic class MyLoginService\n{\n    public MyLoginService(PublisherOf\u003cICustomerLoggedInEvent\u003e customerLoggedInEventPublisher)\n    {\n        _customerLoggedInEventPublisher = customerLoggedInEventPublisher;\n    }\n\n    public void DoStuff()\n    {\n        _customerLoggedInEventPublisher.ForEachSubscriber().DoThis();\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomhurst%2FAllOf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomhurst%2FAllOf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomhurst%2FAllOf/lists"}