1

So I have been struggling around this for some time now.

I have some SuperAwesome™ abstract classes which implement various commonly used snippets of code.

This one implement the INotifyPropertyChanged quite nicely and I don't want to cut and paste it around in my code:

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
}

This other one does something else:

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
}

...And so on.

While I can inherit a class from either of these, I can't inherit from more than one. I know the "common" solution for c# lacking multiple inheritance is to use interfaces but I have yet to find a way to get the actual code written only once and not cut-and-pasted all around. I've looked briefly at extension methods, but the result looked like a mess.. I also though about macros but c# don't get those either..

So my question is how do I prevent cut-and-pasting those snippets in all my children classes and make modification a nightmare...

EDIT: I have given a try at composition and... wow, I feel let down by C# for the first time. If composition is the best way to achieve this, there is something broken. Am I missing something?

Here is a try at compositing INotifyPropertyChanged with some added benefits; I cannot figure out how to get rid of the OnPropertyChanged's code cut and paste; also interfaces forces everything to be public...:

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
        }
    }
}

Unless I am missing something or it could be done better I don't really expect an answer here... consider this my final /rant on c# missing multiple inheritance.

2
  • 4
    Use composition, not inheritance. Commented Mar 6, 2016 at 5:58
  • Thanks, I will give it a try. Commented Mar 6, 2016 at 15:54

2 Answers 2

2

You may create multiple classes implementing the code for all the required behaviours (for example NotifyPropertyChangedBehaviour, DisposableSingletonBehaviour, EditableObjectBehaviour) and then include the instances of all the required behaviours into each one of your classes (composition). Then you need to create proxy methods for the interfaces your class implements and just pass the call to the relevant behaviour class. This way your class may implement unlimited number of behaviours and interfaces.

For example:

class myClass : IMayDoSomething, IMayDoSomethingElse
{
   DoSomethingBehaviour m_doSomethingBehaviour;
   public void DoSomething()
   {
       m_doSomethingBehaviour.DoSomething();
   }

   DoSomethingElseBehaviour m_doSomethingElseBehaviour;
   public void DoSomethingElse()
   {
       m_doSomethingElseBehaviour.DoSomethingElse();
   }

}

public class DoSomethingBehaviour
{
    public void DoSomething()
    {
        // All the code of the method which appears just once, no 
        // copy-paste in classes implementing the behaviour
    }
}
...

You may see some examples in this article: Simulating Multiple Inheritance in C#: Part I
And also see the "Head First Design Patterns" book, see the "Designing the Ducks Behaviors", the example explains the point in a very clear way: Head First Design Patterns

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot, this is the answer I needed.
1

You should ask yourself why do you need both InotifyPropertyChanhed and Disposable Singleton.

As I see it you have a view model which must inherit InotifyPropertyChanged. However I'm not sure that it should also be a disposable singleton...I advice you to use composition for that singleton meaning that your view model will have a property of that sigleton that will be a shared single object across all you app

1 Comment

The point here is not what design pattern should be used, but rather how to code them only once and use them around without cut&paste, something multiple inheritance is very good for.. As you guys are answering me, I guess composition is the best way to achieve this

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.