{"id":22493333,"url":"https://github.com/ufcpp/mixingenerator","last_synced_at":"2025-08-03T01:32:03.058Z","repository":{"id":33318731,"uuid":"36963473","full_name":"ufcpp/MixinGenerator","owner":"ufcpp","description":"A Code-Aware library for giving additional functionality by composition-over-inheritance, a mixin-like approach.","archived":false,"fork":false,"pushed_at":"2022-07-05T10:37:04.000Z","size":185,"stargazers_count":7,"open_issues_count":9,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-01T00:30:12.016Z","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/ufcpp.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":"2015-06-06T01:44:33.000Z","updated_at":"2024-09-05T13:15:25.000Z","dependencies_parsed_at":"2022-08-31T17:20:58.408Z","dependency_job_id":null,"html_url":"https://github.com/ufcpp/MixinGenerator","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/ufcpp%2FMixinGenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ufcpp%2FMixinGenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ufcpp%2FMixinGenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ufcpp%2FMixinGenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ufcpp","download_url":"https://codeload.github.com/ufcpp/MixinGenerator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228514179,"owners_count":17932358,"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-12-06T18:38:40.242Z","updated_at":"2024-12-06T18:38:40.768Z","avatar_url":"https://github.com/ufcpp.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MixinGenerator\n\n- analyzer \u0026 code fix: [MixinGenerator](https://www.nuget.org/packages/MixinGenerator/)\n- common mixins: [MixinGenerator.Mixins](https://www.nuget.org/packages/MixinGenerator.Mixins/)\n\n## How to use\n\n1. Composition\n\n![Composition](docs/Composition.png)\n\n2. Quick Action (C# Analyzer \u0026 Code Fix))\n\n![Code Fix](docs/CodeFix.png)\n\n3. Delegation (Generated Source Code)\n\n![Delegation](docs/Delegation.png)\n\n## Why composition over inheritance\n\n### mixins VS base classes\n\nA class can have multiple mixins.\n\n```cs\n// base class\n// ❌ multiple inheritance (compilation error)\nclass Inheritance : BindableBase, DisposableBase\n{\n}\n\n// mixin\n// ⭕ multiple mixins\nclass Composition\n{\n    // MixinGenerator/MixinGenerator.Mixins/Mixins/NotifyPropertyChanged.cs\n    NotifyPropertyChanged _npc;\n\n    // MixinGenerator/MixinGenerator.Mixins/Mixins/DisposableList.cs\n    DisposableList _d;\n}\n\nclass BindableBase : INotifyPropertyChanged\n{\n    public event PropertyChangedEventHandler PropertyChanged;\n\n    protected void OnPropertyChanged(string propertyName) =\u003e PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n}\n\nclass DisposableBase : IDisposable\n{\n    private List\u003cIDisposable\u003e _disposables = new List\u003cIDisposable\u003e();\n\n    public void Dispose()\n    {\n        foreach (var d in _disposables) d?.Dispose();\n        _disposables.Clear();\n    }\n}\n```\n\n### mixins VS interface default methods\n\nMixins can have state.\n\n```cs\n// interface\n// (C# 8.0 allows interface to have default method implementation)\ninterface INotifyPropertyChanged\n{\n    //❌ This is an abstract declaration. There is no backing field in the interface\n    event PropertyChangedEventHandler PropertyChanged;\n\n    protected void OnPropertyChanged(string propertyName) =\u003e PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n}\n\ninterface ICompositeDisposable : IDisposable\n{\n    //❌ An intarface can't have fields\n    private List\u003cIDisposable\u003e _disposables = new List\u003cIDisposable\u003e();\n\n    void Dispose()\n    {\n        foreach (var d in _disposables) d?.Dispose();\n        _disposables.Clear();\n    }\n}\n\n// mixin\n// ⭕ state (fields)\n[NonCopyable]\n[Mixin]\npublic struct NotifyPropertyChanged : INotifyPropertyChanged\n{\n    // has a backing field for the event\n    public event PropertyChangedEventHandler PropertyChanged;\n\n    [Accessibility(Accessibility.Protected)]\n    public void OnPropertyChanged([This] object @this, PropertyChangedEventArgs args) =\u003e PropertyChanged?.Invoke(@this, args);\n}\n\n[NonCopyable]\n[Mixin]\npublic struct DisposableList : IDisposable\n{\n    // has a field\n    private List\u003cIDisposable\u003e _list;\n\n    public void Dispose()\n    {\n        var list = _list;\n        _list = null;\n        foreach (var d in list) d.Dispose();\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fufcpp%2Fmixingenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fufcpp%2Fmixingenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fufcpp%2Fmixingenerator/lists"}