所以我一直在努力解決這個問題一段時間了。如何防止C#中的代碼重複多個繼承
我有一些SuperAwesome™抽象類實現各種常用的代碼片段。
這一個實現INotifyPropertyChanged相當不錯,我不希望削減它在我的代碼粘貼左右:
public abstract class INotifyPropertyChangedImplementor : INotifyPropertyChanged
{
#region INotifyPropertyChanged Support
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
#endregion
}
這另一個則別的東西:
public abstract class IDisposableSingletonImplementor<T> : IDisposable where T : new()
{
#region Disposable singleton
public static T Instance
{
get
{
if (_Instance == null)
{
_Instance = new T();
}
return _Instance;
}
}
protected static T _Instance = default(T);
public static void DisposeInstance()
{
((IDisposable)_Instance)?.Dispose();
_Instance = default(T);
}
public static bool IsInstanceCreated
{
get
{
return _Instance != null;
}
}
#endregion
#region IDisposable Support
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
DisposeManaged();
}
DisposeUnmanaged();
// TODO: set large fields to null.
disposedValue = true;
}
}
private bool disposedValue = false;
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
//only enable this is destructor is present
//GC.SuppressFinalize(this);
}
protected abstract void DisposeManaged();
protected abstract void DisposeUnmanaged();
#endregion
}
.. 。等等。
雖然我可以繼承其中任何一個類,但我不能從多個繼承。我知道缺乏多重繼承的c#的「常用」解決方案是使用接口,但我還沒有找到一種方法來只寫一次實際的代碼,而不是全部剪切和粘貼。我簡單地看了一下擴展方法,但結果看起來像一團糟..我也雖然關於宏,但C#沒有得到那些..
所以我的問題是如何防止剪切和粘貼在我所有的少兒班的片段,並進行修改的噩夢......
編輯:我已經給在組成一個嘗試,...哇,我感到失望的C#首次。如果構圖是實現這一目標的最佳途徑,那麼就會有某些東西被破壞。我錯過了什麼嗎?
這是一個嘗試合成INotifyPropertyChanged與一些額外的好處;我無法弄清楚如何擺脫OnPropertyChanged的代碼剪切和粘貼;接口也一切力量是公共...:
public interface INotifyPropertyChangedEx : INotifyPropertyChanged
{
//i dont want these public but i want to force their implementation in child classes...
bool SetField<T>(ref T field, T value, string propertyName);
void OnPropertyChanged(string propertyName);
}
public class INotifyPropertyChangedBehavior : INotifyPropertyChangedImplementor
{
}
public abstract class INotifyPropertyChangedImplementor : INotifyPropertyChangedEx
{
//this is the code i dont want to replicate
#region INotifyPropertyChanged Support
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null) //public yuck
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public bool SetField<T>(ref T field, T value, string propertyName) //public yuck
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
#endregion
}
//so try at imlpementation..
public class Test1 : INotifyPropertyChangedImplementor
{
//wow such easy implementation, nothing to do!!
//some actual data
private string _Name;
public string Name
{
get
{
return _Name;
}
set
{
SetField(ref _Name, value, nameof(Name));
}
}
}
public class Test2 : INotifyPropertyChangedEx
{
public event PropertyChangedEventHandler PropertyChanged;//created from interface
//the composition behavior object
private INotifyPropertyChangedBehavior NotifyPropertyChangedBehavior = new INotifyPropertyChangedBehavior();
public bool SetField<T>(ref T field, T value, string propertyName)//created from interface
{
return NotifyPropertyChangedBehavior.SetField(ref field, value, propertyName);//actual code reuse, yay
}
public void OnPropertyChanged(string propertyName)//created from interface
{
//cannot reuse code here, other classes wont register my internal NotifyPropertyChangedBehavior.PropertyChanged...
//composition fail miserably for events, so this is a cut and paste
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
//some actual data
private string _Name;
public string Name
{
get
{
return _Name;
}
set
{
SetField(ref _Name, value, nameof(Name));
}
}
}
public class main
{
//both Test1 (inherited) and Test2 (composited) classes should be usable in the same exact way
Test1 test1 = new Test1();
Test2 test2 = new Test2();
public main()
{
test1.PropertyChanged += Test1_PropertyChanged;
test2.PropertyChanged += Test2_PropertyChanged;
}
private void Test1_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(test1.Name))
{
//react
}
}
private void Test2_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(test2.Name))
{
//react
}
}
}
除非我失去了一些東西,或者它可以做更好,我從來沒有真正想過的答案在這裏......考慮在C#這是我最後的/咆哮失蹤多重繼承。
使用組合,而不是繼承。 – Dai
謝謝,我會試試看。 –