8

I have a class library with 2 public classes that inherit from an abstract class. On the abstract class I have a protected field that should only be accessible to the inherited classes. The type used for the field is that of an internal class.

For example I have:

internal class MyInternalClass
{
    ...
}

public abstract class MyAbstractClass
{
    protected MyInternalClass myField;
}

Now I understand that this won't work because if one of the classes deriving from MyAbstract class is extended outside of the assembly, access to myField would be illegal.

My question is how can I get things working while keeping MyInternalClass internal (it should not be accessible outside the assembly) and allowing classes within the assembly to extend MyAbstractClass with access to myField?

zaq
  • 2,571
  • 3
  • 31
  • 39

4 Answers4

6

Create a public interface that MyAbstractClass requires and MyInternalClass implements.

Something like this so you can have it be MyInternalClass by default but inject new behavior if you needed (for example, mocking):

internal class MyInternalClass : IMyInterface
{
}

public interface IMyInterface
{            
}

public abstract class MyAbstractClass
{
    protected IMyInterface myField;

    protected MyAbstractClass(IMyInterface required = null)
    {
        myField = required ?? new MyInternalClass();
    }
}
Austin Salonen
  • 49,173
  • 15
  • 109
  • 139
  • 3
    You can also store the internal class reference in a private field, then provide a protected property exposing it as the public interface. This has the side benefit of allowing you to further restrict the access to the internal class (via the interface) to only what is needed by derivers from MyAbstractClass. It also gives you flexibility if this interface ever gets implemented differently (such as by decomposing its functionality into two helper classes instead of one, for instance.) – Dan Bryant Sep 19 '12 at 21:46
  • @DanBryant: Very true. Good suggestion. – Austin Salonen Sep 19 '12 at 21:59
0

You can't. If MyAbstractClass is derived from in an external class MyInternalClass needs to be known.

If you need to think about things like this, the design might need rework.

EricSchaefer
  • 25,272
  • 21
  • 67
  • 103
0

You are in need of a keyword that specifies protected "and" internal instead of protected "or" internal. Such a keyword does not exist (as of C# 5.0). They could add it in later versions.

There are very many threads on this in here. Se for example question 5596338.

ADDITION: Now I have come up with this "solution":

public abstract class MyAbstractClass
{
    protected class AccessMyFieldHelper
    {
        internal MyInternalClass this[MyAbstractClass mac]
        {
            get { return mac.myField; }
            set { mac.myField = value; }
        }
    }
    protected static readonly AccessMyFieldHelper AccessMyField = new AccessMyFieldHelper();

    private MyInternalClass myField;
}

The myField is now private, but there is protected access to it through the AccessMyField. As it is an indexer, you will have to use square brackets [].

What do you think? Can this be done more beautifully?

Community
  • 1
  • 1
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
-1

Make the field myField internal protected.

You also have to make MyAbstractClass internal. There's no way it can be public if it inherits from an internal class. If the class has to be public, then there has to be a way to work around it: for example, create an interface that exposes the functionality of MyInternalClass that the inheriting classes need.

McGarnagle
  • 101,349
  • 31
  • 229
  • 260