Reputation: 14431
Lets say I have a class library, where any classes that are internal have access to the following interface:
interface myInterface
{
string myProperty { get; set; } // notice setter.
}
But if somebody adds this class library to their project they get the following interface:
public interface myInterface
{
string myProperty { get; }
}
What is the most efficient and accepted way of doing this? Have one interface implement the other?
Upvotes: 6
Views: 2332
Reputation: 13085
You can have the internal interface extend the public interface, like so:
public interface MyInternalInterface: MyPublicInterface
{
string MyProperty { set; }
}
public interface MyPublicInterface
{
string MyProperty { get; }
}
internal class A: MyInternalInterface
{
public string MyProperty { get; set; }
}
public class Foo
{
private A _a = new A();
internal MyInternalInterface GetInternalA() { return _a; }
public MyPublicInterface GetA() { return _a; }
}
This way you don't need any casts or anything.
Upvotes: 1
Reputation: 42363
I thought that @adrianbanks' answer might be an improvement on mine, however I don't think it really is (despite being nifty) - because you have no guarantee that a public interface instance being passed to you also implements the internal one - which is also true of this solution. There's also the thing that it only works if the implementing type is internal
- which is no good if you want to supply public types as standard interface implementations or as bases for a hierarchy.
This is what I use. Given:
interface myInterface
{
string myProperty { get; set; }
}
public interface myPublicInterface
{
string myProperty { get; }
}
First you can't make myPublicInterface
inherit myInterface
because the compiler will moan about inconsistent accessibility. So you can explicitly implement the internal one, using a property backer, and then implement the public one implicitly:
public class MyClass : myInterface, myPublicInterface
{
private string _myProperty;
string myInterface.myProperty
{
get { return _myProperty; }
set { _myProperty = value; }
}
public string myProperty
{
get { return _myProperty; }
}
}
Note - in some cases, the getter might not be suitable for a private backer, but might be some logic that calculates values from other properties. In which case - to keep it DRY - you can put the logic in the public getter, and leech that for the explicit getter:
string myInterface.myProperty
{
get { return MyProperty; }
set { /*whatever logic you need to set the value*/ }
}
public string myProperty
{
get { /*whatever complex logic is used to get the value*/ }
}
You can do it the other way around, but you have to do a horrible-looking inline cast to the internal interface:
string myInterface.myProperty
{
get { /*whatever complex logic is used to get the value*/ }
set { /*whatever logic you need to set the value*/ }
}
public string myProperty
{
get { return ((myInterface)this).myProperty; }
}
Which you should try to steer clear of wherever possible.
Upvotes: 0
Reputation: 83004
Make your public interface have just the getter:
public interface myInterface
{
string myProperty { get; }
}
And then derive another internal-only interface from it that has a setter:
internal interface myInternalInterface : myInterface
{
new string myProperty { get; set; }
}
You can them implement the internal interface:
class myImplementation : myInternalInterface
{
public string myProperty{get; set;}
}
If you need to call the setter, you can cast your instance to the internal inteface and call it on that. This approach is a bit of a design smell though, so use it sparingly.
Upvotes: 2