0

I'm looking for a way to share the implementation of two classes without exposing any details of that sharing. I was hoping to create this basic class structure:

  • public interface MyInterface
  • class MyCommonImpl : MyInterface
  • public class MyImplA : MyCommonImpl
  • public class MyImplB : MyCommonImpl

MyCommonImpl implements the functions of MyInterface and has one abstract function provided in MyImplA and MyImplB. A user of MyImplA should not know about MyCommonImpl in any fashion, it's just an implentation detail.

I've considered doing manual composition, but this involves copying a lot of code to forward the functions. It's also problematic since there are events implemented in MyCommonImpl, and one of their parameters is a sender. This requires putting a proxy handler and partially rewriting events. Basically composition would require more code than simply copy-pasting the entire MyCommonImpl.

How can I do this without having to duplicate a lot of code?

edA-qa mort-ora-y
  • 30,295
  • 39
  • 137
  • 267
  • 2
    I don't quite understand the question; the design presented in the question totally makes sense. What is the reason for hiding `MyCommonImpl` to `MyImplA` and `MyImplB`? – Codor Dec 03 '14 at 08:07
  • We don't want to expose `MyCommonImpl` in the module. That is, users of the library should not see it since it then becomes part of the public interface. As I understand I can't actually do the above, use a private base class for inheritence to a public class. – edA-qa mort-ora-y Dec 03 '14 at 08:12
  • Use composition, not inheritance - [Wikipedia: Composition over inheritance](http://en.wikipedia.org/wiki/Composition_over_inheritance) – Lasse V. Karlsen Dec 03 '14 at 08:13
  • @LasseV.Karlsen, I've explained why I don't want to use composition. It involves basically copy-paste on the code and involves intercepting event callbacks. – edA-qa mort-ora-y Dec 03 '14 at 08:16
  • Well, you can't create a public class that inherits from an internal one. – Lasse V. Karlsen Dec 03 '14 at 08:16
  • MyCommonImpl is an abstract class implementing your MyInterface, correct? You are not exposing it since no one can instantiate MyCommonImpl anyway. If there are public methods you're worried about exposing, why are they public in the first place? Can't they be protected instead? Without some sample code it's very difficult to see why exactly you're trying to avoid by hiding MyCommonImpl. – kha Dec 03 '14 at 08:18
  • possible duplicate of [C# private (hidden) base class](http://stackoverflow.com/questions/10858107/c-sharp-private-hidden-base-class) – Benjamin Hodgson Dec 03 '14 at 08:18

1 Answers1

1

You can move the interfaces and implementations to another assembly and mark them internal which will hide the abstract function of MyCommonImpl. Taking it further, you could explicitly implement the interfaces inside that assembly to completely hide their methods from callers leaving only those methods declared public on MyImplA visible.

The internal casts for the explicit implementation are a bit nasty though...

In a separate assembly:

namespace Private
{
    internal interface IMyInterface
    {
        void InterfaceMethod();
    }

    public abstract class MyCommonImpl : IMyInterface
    {
        internal MyCommonImpl()
        {
            // internal ctor to stop callers constructing
        }

        void IMyInterface.InterfaceMethod()
        {
            Console.WriteLine("InterfaceMethod");
        }

        internal abstract void CommonAbstract();
    }

    public class MyImplA : MyCommonImpl
    {
        internal override void CommonAbstract()
        {
            ((IMyInterface)this).InterfaceMethod();
            Console.WriteLine("CommonAbstract");
        }

        public void ImplAMethod()
        {
            CommonAbstract();
            Console.WriteLine("ImplAMethod");
        }
    }
}
MarcE
  • 3,586
  • 1
  • 23
  • 27