{"id":13628843,"url":"https://github.com/notanaverageman/Depso","last_synced_at":"2025-04-17T04:32:29.440Z","repository":{"id":146864152,"uuid":"604544226","full_name":"notanaverageman/Depso","owner":"notanaverageman","description":"C# source generator for dependency injection allowing a subset of the language instead of using attributes.","archived":false,"fork":false,"pushed_at":"2025-02-14T19:45:49.000Z","size":237,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-06T04:38:02.650Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/notanaverageman.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-21T09:33:03.000Z","updated_at":"2025-02-14T19:45:54.000Z","dependencies_parsed_at":"2024-05-11T23:25:55.016Z","dependency_job_id":null,"html_url":"https://github.com/notanaverageman/Depso","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/notanaverageman%2FDepso","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/notanaverageman%2FDepso/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/notanaverageman%2FDepso/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/notanaverageman%2FDepso/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/notanaverageman","download_url":"https://codeload.github.com/notanaverageman/Depso/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249315996,"owners_count":21249871,"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-08-01T22:00:58.341Z","updated_at":"2025-04-17T04:32:29.433Z","avatar_url":"https://github.com/notanaverageman.png","language":"C#","funding_links":[],"categories":["Content"],"sub_categories":["144. [depso](https://ignatandrei.github.io/RSCG_Examples/v2/docs/depso) , in the [DependencyInjection](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#dependencyinjection) category"],"readme":"# Depso Dependency Injection Source Generator\r\n\r\n[![NuGet Depso](https://img.shields.io/nuget/v/Depso.svg?label=Depso)](https://www.nuget.org/packages/Depso/)\r\n[![AppVeyor](https://img.shields.io/appveyor/ci/notanaverageman/depso.svg)](https://ci.appveyor.com/project/notanaverageman/depso)\r\n\r\nDepso is yet another source generator for dependency injection. However, it takes a different approach than existing\r\nsource generators and uses a restricted subset of C# instead of using attributes to define dependencies. This leads to\r\na more natural and readable code and allows for more extension points.\r\n\r\nBehavior of the generated code is similar to the `IServiceCollection` interface in ASP.NET Core. For more information on\r\nhow to use dependency injection, see the [official documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection).\r\n\r\nExamples of generated code can be found in the [Test](Depso.Test/SourceCodes/Generators) project.\r\n\r\n## Features\r\n\r\n- Clean and readable service registration code and generated code.\r\n- No reflection or runtime code generation.\r\n- Registering services with singleton, scoped, and transient lifetimes.\r\n- Registering services as multiple types.\r\n- Registering services using factory methods.\r\n- Compile-time validation of missing service registrations.\r\n- Resolving `IEnumerable\u003cT\u003e` services.\r\n- Disposing of services that implement `IDisposable` or `IAsyncDisposable`.\r\n- Grouping service registrations in modules and importing these registrations in service providers.\r\n\r\n## Usage\r\n\r\nAdd the `Depso` package to your project:\r\n\r\n```xml\r\n\u003cItemGroup\u003e\r\n    \u003cPackageReference Include=\"Depso\" Version=\"1.0.2\" PrivateAssets=\"all\" /\u003e\r\n\u003c/ItemGroup\u003e\r\n```\r\n\r\n### Basic Usage\r\n\r\nServices are registered by calling the `AddSingleton`, `AddScoped`, and `AddTransient` methods. It is possible to use the generic overloads\r\nor the non-generic overloads that accept a `Type` parameter. The end result is exactly the same. Services can be registered as their own type\r\nor as their base types or implemented interfaces.\r\n\r\n```csharp\r\nusing Depso;\r\n\r\npublic interface ITransientInterface { }\r\npublic class Singleton { }\r\npublic class Scoped { }\r\npublic class Transient : ITransientInterface { }\r\npublic class TypeOf { }\r\n\r\n// Decorate the class with the ServiceProvider attribute.\r\n[ServiceProvider]\r\npublic partial class Container\r\n{\r\n    // Declare the method to register services. Its signature must be\r\n    // private void and it must be named as RegisterServices.\r\n    private void RegisterServices()\r\n    {\r\n        // Register services by calling the AddSingleton, AddScoped, and AddTransient methods.\r\n        AddSingleton\u003cSingleton\u003e();\r\n        AddScoped\u003cScoped\u003e();\r\n        // Service can only be resolved as an ITransientInterface.\r\n        AddTransient\u003cITransientInterface, Transient\u003e();\r\n\r\n        // Register using typeof expressions.\r\n        AddTransient(typeof(TypeOf));\r\n    }\r\n}\r\n```\r\n\r\n### Registering Services as Multiple Types\r\n\r\nIt is frequently needed to register a service as multiple types. Normally, this is done by registering the other types using factory\r\nmethods and resolving the service in these methods using the passed `IServiceProvider`. This library provides `AlsoAs` and `AlsoAsSelf`\r\nmethods to register a service as multiple types and reduce the boilerplate code.\r\n\r\n```csharp\r\nusing Depso;\r\n\r\npublic interface SingletonInterface { }\r\npublic interface ScopedInterface { }\r\npublic interface TransientInterface { }\r\npublic class Singleton : SingletonInterface { }\r\npublic class Scoped : ScopedInterface { }\r\npublic class Transient : TransientInterface { }\r\n\r\n[ServiceProvider]\r\npublic partial class Container\r\n{\r\n    private void RegisterServices()\r\n    {\r\n        // Register a service as its own type and also as an interface.\r\n        AddSingleton\u003cSingleton\u003e().AlsoAs\u003cSingletonInterface\u003e();\r\n        AddScoped(typeof(Scoped)).AlsoAs(typeof(ScopedInterface));\r\n        \r\n        // Register a service as an interface and also as its own type.\r\n        AddTransient\u003cTransientInterface, Transient\u003e().AlsoAsSelf();\r\n    }\r\n}\r\n```\r\n\r\n### Factories\r\n\r\nFactory methods can be used to create services manually or register existing instance objects. `AddX` methods have overloads that accept\r\na factory method of type `Func\u003cIServiceProvider, T\u003e`. It is possible to use static methods, instance methods, and lambda\r\nexpressions as factory methods.\r\n\r\n```csharp\r\nusing Depso;\r\n\r\npublic class Member { }\r\npublic class Lambda { }\r\npublic class Static { }\r\npublic class Instance { }\r\n\r\n[ServiceProvider]\r\npublic partial class Container\r\n{\r\n    private readonly Member _member;\r\n\r\n    public Container(Member member)\r\n    {\r\n        _member = member;\r\n    }\r\n\r\n    private void RegisterServices()\r\n    {\r\n        // Register an object instance.\r\n        AddTransient(_ =\u003e _member);\r\n\r\n        // Register a service using a lambda.\r\n        AddTransient(_ =\u003e new Lambda());\r\n\r\n        // Register a service using a static factory method.\r\n        AddTransient(CreateStatic);\r\n\r\n        // Register a service using an instance factory method.\r\n        AddTransient(CreateInstance);\r\n    }\r\n\r\n    private static Static CreateStatic(IServiceProvider _) =\u003e new Static();\r\n    private Instance CreateInstance(IServiceProvider _) =\u003e new Instance();\r\n}\r\n```\r\n\r\n### Modules\r\n\r\nModules can be used to group related services together. Modules can be nested and can reference other modules. Modules that are defined\r\non other assemblies can also be imported. In this case, the types that are registered in the imported module must be accessible by the declaring\r\nservice provider.\r\n\r\nThe `RegisterServices` method has to be `static` on modules. This means that modules can't use instance members.\r\n\r\n```csharp\r\nusing Depso;\r\n\r\npublic class ModuleFactory { }\r\npublic class ModuleService { }\r\npublic class OtherModuleService { }\r\n\r\n[ServiceProviderModule]\r\npublic partial class Module\r\n{\r\n    private static void RegisterServices()\r\n    {\r\n        // Registration of services is the same as in the service provider.\r\n        AddSingleton\u003cModuleService\u003e();\r\n        // Modules can import other modules.\r\n        ImportModule\u003cOtherModule\u003e();\r\n    }\r\n}\r\n\r\n[ServiceProviderModule]\r\npublic partial class OtherModule\r\n{\r\n    private static void RegisterServices()\r\n    {\r\n        AddSingleton\u003cOtherModuleService\u003e();\r\n    }\r\n}\r\n\r\n[ServiceProvider]\r\npublic partial class Container\r\n{\r\n    private void RegisterServices()\r\n    {\r\n        ImportModule\u003cModule\u003e();\r\n    }\r\n}\r\n```\r\n\r\n## Performance\r\n\r\nThe benchmark project is similar to the one in [Jab](https://github.com/pakrym/jab/tree/main/src/Jab.Performance) project. However, all\r\nservice providers are treated as `IServiceProvider` and the `IServiceProvider` interface is used to resolve services.\r\n\r\nThe differences between this library and Jab should probably be negligible when used in real-world applications.\r\n\r\n### Service Registration and First Resolve\r\n\r\n```text\r\nBenchmarkDotNet v0.13.12, Windows 11 (10.0.22621.2134/22H2/2022Update/SunValley2)\r\nIntel Core i9-10900K CPU 3.70GHz, 1 CPU, 20 logical and 10 physical cores\r\n.NET SDK 8.0.202\r\n  [Host]     : .NET 8.0.3 (8.0.324.11423), X64 RyuJIT AVX2\r\n  DefaultJob : .NET 8.0.3 (8.0.324.11423), X64 RyuJIT AVX2\r\n\r\n\r\n| Method | Mean        | Error     | StdDev    | Ratio | RatioSD | Gen0   | Gen1   | Allocated | Alloc Ratio |\r\n|------- |------------:|----------:|----------:|------:|--------:|-------:|-------:|----------:|------------:|\r\n| MEDI   | 1,069.95 ns | 20.338 ns | 20.886 ns | 71.29 |    2.33 | 0.5188 | 0.0095 |    5432 B |       61.73 |\r\n| Jab    |    15.86 ns |  0.207 ns |  0.194 ns |  1.06 |    0.03 | 0.0053 |      - |      56 B |        0.64 |\r\n| Depso  |    15.02 ns |  0.322 ns |  0.331 ns |  1.00 |    0.00 | 0.0084 |      - |      88 B |        1.00 |\r\n```\r\n\r\n### Service Resolution\r\n\r\n```text\r\nBenchmarkDotNet v0.13.12, Windows 11 (10.0.22621.2134/22H2/2022Update/SunValley2)\r\nIntel Core i9-10900K CPU 3.70GHz, 1 CPU, 20 logical and 10 physical cores\r\n.NET SDK 8.0.202\r\n  [Host]     : .NET 8.0.3 (8.0.324.11423), X64 RyuJIT AVX2\r\n  DefaultJob : .NET 8.0.3 (8.0.324.11423), X64 RyuJIT AVX2\r\n\r\n\r\n| Method | Mean      | Error     | StdDev    | Ratio | RatioSD | Gen0   | Allocated | Alloc Ratio |\r\n|------- |----------:|----------:|----------:|------:|--------:|-------:|----------:|------------:|\r\n| MEDI   | 19.857 ns | 0.0458 ns | 0.0406 ns |  2.32 |    0.02 | 0.0023 |      24 B |        1.00 |\r\n| Jab    | 11.937 ns | 0.0528 ns | 0.0468 ns |  1.39 |    0.01 | 0.0023 |      24 B |        1.00 |\r\n| Depso  |  8.569 ns | 0.0651 ns | 0.0609 ns |  1.00 |    0.00 | 0.0023 |      24 B |        1.00 |\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnotanaverageman%2FDepso","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnotanaverageman%2FDepso","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnotanaverageman%2FDepso/lists"}