https://github.com/ufcpp/mixingenerator
A Code-Aware library for giving additional functionality by composition-over-inheritance, a mixin-like approach.
https://github.com/ufcpp/mixingenerator
Last synced: 6 months ago
JSON representation
A Code-Aware library for giving additional functionality by composition-over-inheritance, a mixin-like approach.
- Host: GitHub
- URL: https://github.com/ufcpp/mixingenerator
- Owner: ufcpp
- License: mit
- Created: 2015-06-06T01:44:33.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2022-07-05T10:37:04.000Z (over 3 years ago)
- Last Synced: 2024-12-01T00:30:12.016Z (about 1 year ago)
- Language: C#
- Size: 181 KB
- Stars: 7
- Watchers: 3
- Forks: 1
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# MixinGenerator
- analyzer & code fix: [MixinGenerator](https://www.nuget.org/packages/MixinGenerator/)
- common mixins: [MixinGenerator.Mixins](https://www.nuget.org/packages/MixinGenerator.Mixins/)
## How to use
1. Composition

2. Quick Action (C# Analyzer & Code Fix))

3. Delegation (Generated Source Code)

## Why composition over inheritance
### mixins VS base classes
A class can have multiple mixins.
```cs
// base class
// ❌ multiple inheritance (compilation error)
class Inheritance : BindableBase, DisposableBase
{
}
// mixin
// ⭕ multiple mixins
class Composition
{
// MixinGenerator/MixinGenerator.Mixins/Mixins/NotifyPropertyChanged.cs
NotifyPropertyChanged _npc;
// MixinGenerator/MixinGenerator.Mixins/Mixins/DisposableList.cs
DisposableList _d;
}
class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
class DisposableBase : IDisposable
{
private List _disposables = new List();
public void Dispose()
{
foreach (var d in _disposables) d?.Dispose();
_disposables.Clear();
}
}
```
### mixins VS interface default methods
Mixins can have state.
```cs
// interface
// (C# 8.0 allows interface to have default method implementation)
interface INotifyPropertyChanged
{
//❌ This is an abstract declaration. There is no backing field in the interface
event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
interface ICompositeDisposable : IDisposable
{
//❌ An intarface can't have fields
private List _disposables = new List();
void Dispose()
{
foreach (var d in _disposables) d?.Dispose();
_disposables.Clear();
}
}
// mixin
// ⭕ state (fields)
[NonCopyable]
[Mixin]
public struct NotifyPropertyChanged : INotifyPropertyChanged
{
// has a backing field for the event
public event PropertyChangedEventHandler PropertyChanged;
[Accessibility(Accessibility.Protected)]
public void OnPropertyChanged([This] object @this, PropertyChangedEventArgs args) => PropertyChanged?.Invoke(@this, args);
}
[NonCopyable]
[Mixin]
public struct DisposableList : IDisposable
{
// has a field
private List _list;
public void Dispose()
{
var list = _list;
_list = null;
foreach (var d in list) d.Dispose();
}
}
```