{"id":25501030,"url":"https://github.com/ipjohnson/DependencyModules","last_synced_at":"2025-11-11T22:30:20.575Z","repository":{"id":270906509,"uuid":"910233062","full_name":"ipjohnson/DependencyModules","owner":"ipjohnson","description":null,"archived":false,"fork":false,"pushed_at":"2025-02-13T00:40:34.000Z","size":184,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-13T01:30:00.155Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/ipjohnson.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-30T18:41:51.000Z","updated_at":"2025-02-13T00:40:37.000Z","dependencies_parsed_at":"2025-01-26T19:20:49.998Z","dependency_job_id":"6bfdc26e-48d9-4e39-a6f9-085aed3cb2db","html_url":"https://github.com/ipjohnson/DependencyModules","commit_stats":null,"previous_names":["ipjohnson/dependencymodules"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipjohnson%2FDependencyModules","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipjohnson%2FDependencyModules/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipjohnson%2FDependencyModules/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipjohnson%2FDependencyModules/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ipjohnson","download_url":"https://codeload.github.com/ipjohnson/DependencyModules/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239592970,"owners_count":19664856,"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":"2025-02-19T04:01:58.317Z","updated_at":"2025-11-11T22:30:20.533Z","avatar_url":"https://github.com/ipjohnson.png","language":"C#","funding_links":[],"categories":["Content"],"sub_categories":["185. [DependencyModules.SourceGenerator](https://ignatandrei.github.io/RSCG_Examples/v2/docs/DependencyModules.SourceGenerator) , in the [DependencyInjection](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#dependencyinjection) category"],"readme":"# DependencyModules\n\nDependencyModules is a C# source generator package that uses attributes to create\ndependency injection registration modules. These modules can then be used to populate \nan IServiceCollection instance.\n\n## Installation\n\n```csharp\ndotnet add package DependencyModules.Runtime\ndotnet add package DependencyModules.SourceGenerator\n```\n\n## Service Attributes \n\n* `[DependencyModule]` - used to attribute class that will become dependency module (must be partial)\n* `[SingletonService]` - registers service as `AddSingleton`\n* `[ScopedService]` - registers service as `AdddScoped`\n* `[TransientService]` - registers service as `AddTransient`\n* `[CrossWireService]` - register implementation and interfaces with the same lifetime\n\n```csharp\n// Registration example\n[DependencyModule]\npublic partial class MyModule { }\n\n// registers SomeClass implementation for ISomeService\n[SingletonService]\npublic class SomeClass : ISomeService \n{\n  public string SomeProp =\u003e \"SomeString\";\n}\n\n// registers OtherSerice implementation\n[TransientService]\npublic class OtherService\n{\n  public OtherService(ISomeService service)\n  { \n    SomeProp = service.SomeProp;\n  }\n  public string SomeProp { get; }\n}\n```\n## Container Instantiation\n\n`AddModule` - method adds modules to service collection\n\n```csharp\nvar serviceCollection = new ServiceCollection();\n\nserviceCollection.AddModule\u003cMyModule\u003e();\n\nvar provider = serviceCollection.BuildServiceProvider();\n\nvar service = provider.GetService\u003cOtherService\u003e();\n```\n\n## Factories\n\nSometimes it's not possible to construct all types through normal registration.\nFactories can be registered with a module using the registration attributes.\n\n```csharp\npublic class SomeClass : ISomeInterface {\n  public SomeClass(IDep one, IDepTwo two, DateTime dateTime) { ... }\n  \n  [SingletonService]\n  public static ISomeInterface Factory(IDep one, IDepTwo two) {\n    return new SomeClass(one, two, DateTime.Now());   \n  }\n}\n```\n## Module Re-use\n\nDependencyModules creates an `Attribute` class that can be used to apply sub dependencies.\n\n```csharp\n// Modules can be re-used with the generated attributes\n[DependencyModule]\n[MyModule.Attribute]\npublic partial class AnotherModule { }\n```\n\n## Parameters\n\nSometimes you want to provide extra registration for your module. \nThis can be achieved by adding a constructor to your module or optional properties. \nNote these parameters and properties will be correspondingly implemented in the module attribute.\n\n```csharp\n[DependencyModule]\npublic partial class SomeModule : IServiceCollectionConfiguration \n{\n  private bool _someFlag;\n  public SomeModule(bool someFlag = false)\n  {\n    _someFlag = someFlag;\n  }\n  \n  public string OptionalString { get; set; } = \"\";\n  \n  public void ConfigureServices(IServiceCollection services) \n  {\n    if (_someFlag) \n    {\n      // custom registration\n    } \n  }\n}\n\n[DependencyModule]\n[SomeModule.Attribute(true, OptionalString = \"otherString\")]\npublic partial class SomeOtherModule \n{\n\n}\n```\n\n## Managing duplicate registration\n\nBy default a module will only be loaded once, assuming attributes are used or the modules are specified in the same `AddModules` call. Seperate calls to `AddModule` will result in modules being loaded multiple times. If a module uses parameters it can be useful to load a module more than once. That can be accompilished by overriding the `Equals` and `GetHashcode` methods to allow for multiple loads.\n\nServices will be registered using an `Add` method by default. This can be overriden using the `With` property on individual service or at the `DepedencyModule` level.\n\n```csharp\n[SingletonService(With = RegistrationType.Try)]\npublic class SomeService { }\n\n[DependencyModule(With = RegistrationType.Try)]\npublic partial class SomeModule { }\n```\n\n## Realm\n\nBy default, all dependencies are registered in all modules within the same assembly. \nThe realm allows the developer to scope down the registration within a given module.\n\n```csharp\n// register only dependencies specifically marked for this realm\n[DependencyModule(OnlyRealm = true)]\npublic partial class AnotherModule { }\n\n[SingletonService(ServiceType = typeof(ISomeInterface), \n  Realm = typeof(AnotherModule))]\npublic class SomeDep : ISomeInterface { }\n```\n\n## Keyed Registration\n\nRegistration attributes have a `Key` property that allows for specifying the key at registration time.\n\n```csharp\n[SingletonService(Key = \"SomeKey\")]\npublic class KeyService : IKeyService { }\n\n// yields this registration line\nservices.AddKeyedSingleton(typeof(IKeyService), \"SomeKey\", typeof(KeyService));\n```\n\n## Unit testing \u0026 Mocking\n\nDependencyModules provides an xUnit extension to make testing much easier. \nIt handles the population and construction of a service provider using specified modules.\n\n```csharp\n\u003e dotnet add package DependencyModules.xUnit\n\u003e dotnet add package DependencyModules.xUnit.NSubstitute\n\n// applies module \u0026 nsubstitute support to all tests.\n// test attributes can be applied at the assembly, class, and test method level\n[assemlby: MyModule.Attribute]\n[assembly: NSubstituteSupport]\n\npublic class OtherServiceTests \n{\n  [ModuleTest]\n  public void SomeTest(OtherService test, [Mock]ISomeService service)\n  {\n     service.SomeProp.Returns(\"some mock value\");\n     Assert.Equals(\"some mock value\", test.SomeProp);\n  }\n}\n\n```\n## Implementation\n\nBehind the scenes the library generates registration code that can be used with any `IServiceCollection` compatible DI container.\n\nExample generated code for [SutModule.cs](integ-tests/SutProject/SutModule.cs)\n```csharp\n    // SutModule.Dependencies.g.cs\n    public partial class SutModule\n    {\n        private static int moduleField = DependencyRegistry\u003cSutModule\u003e.Add(ModuleDependencies);\n\n        private static void ModuleDependencies(IServiceCollection services)\n        {\n            services.AddTransient(typeof(IDependencyOne), typeof(DependencyOne));\n            services.AddSingleton(typeof(IGenericInterface\u003c\u003e), typeof(GenericClass\u003c\u003e));\n            services.AddScoped(typeof(IScopedService), typeof(ScopedService));\n            services.AddSingleton(typeof(ISingletonService), typeof(SingletonService));\n            services.AddSingleton(typeof(IGenericInterface\u003cstring\u003e), typeof(StringGeneric));\n        }\n    }\n\n    // SutModule.Modules.g.cs\n    public partial class SutModule : IDependencyModule\n    {\n        static SutModule()\n        {\n        }\n\n        // this method loads all dependencies into IServiceCollection.\n        public void PopulateServiceCollection(IServiceCollection services)\n        {\n            DependencyRegistry\u003cSutModule\u003e.LoadModules(services, this);\n        }\n\n        void IDependencyModule.InternalApplyServices(IServiceCollection services)\n        {\n            DependencyRegistry\u003cSutModule\u003e.ApplyServices(services);\n        }\n\n        public override bool Equals(object? obj)\n        {\n            return obj is SutModule;\n        }\n\n        public override int GetHashCode()\n        {\n            return HashCode.Combine(base.GetHashCode());\n        }\n\n        public class Attribute : System.Attribute, IDependencyModuleProvider\n        {\n            public IDependencyModule GetModule()\n            {\n                var newModule = new SutModule();\n                return newModule;\n            }\n        }\n    }\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fipjohnson%2FDependencyModules","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fipjohnson%2FDependencyModules","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fipjohnson%2FDependencyModules/lists"}