Internal Interfaces
Occasionally there is the need to expose, for the purposes of an API or such like, a property of a class that has different external and internal implementations. Consider the code below: a person class with an Id property that is set to -1 by default with an external get property and an internal set property.
public class Person
{
private int _id = -1; // default value
public int Id
{
get { return this._id; }
internal set { this._id = value; }
}
}
If there are several classes that implement the Id property in this manner and there is a need to reference them through a common interface externally then implementing the following on each of the classes should be sufficient:
public interface IIdentifiable
{
int Id { get; }
}
However, to reference these classes internally using the same common interface may be insufficient as it does not allow a call to the internal set property. Clearly it would not be efficient, or necessarily easy, to cast the classes to their individual types prior to making the call. One solution is to use a separate interface for internal operations; an interface with internal scope:
internal interface IIdentifiableInternal : IIdentifiable
{
new int Id { get; set; }
}
Here, we implement the IIdentifiable interface and declare the Id property as new, effectively hiding its IIdentifiable implementation. We don’t reflect this in quite the same manner in our implementation of the IIdentifiableInternal interface on our class though. Instead, we explicitly implement the IIdentifiableInternal interface:
public class Person : IIdentifiableInternal
{
private int _id = -1; // default value
public int Id
{
get { return this._id; }
}
int IIdentifiableInternal.Id
{
get { return this._id; }
set { this._id = value; }
}
}
The external members of the class now include the public get method of the Id property, as does the public IIdentifiable interface. However, internally the class can be referenced using the IIdentifiableInternal interface which allows access to both the get and set methods of the property.
What has been demonstrated is how to take a number of classes with common members that have both public and internal scope and provide a means to reference them through a common interface, both internally and externally.
As a final point, if you have a linked library which you want to have access to the internal interfaces then you can use the following assembly attribute to expose internal to the specified assembly:
[assembly: InternalsVisibleTo("MyLibrary.InterfaceExample")]