假设我有一个类库,其中任何内部类都可以访问以下接口:
interface myInterface
{
string myProperty { get; set; } // notice setter.
}
但是如果有人将这个类库添加到他们的项目中,他们会得到以下接口:
public interface myInterface
{
string myProperty { get; }
}
这样做的最有效和最被接受的方式是什么?有一个接口实现另一个接口吗?
让你的公共接口只有 getter:
public interface myInterface
{
string myProperty { get; }
}
然后从中派生另一个具有 setter 的内部接口:
internal interface myInternalInterface : myInterface
{
new string myProperty { get; set; }
}
你可以让他们实现内部接口:
class myImplementation : myInternalInterface
{
public string myProperty{get; set;}
}
如果您需要调用设置器,您可以将您的实例转换为内部接口并在其上调用它。不过,这种方法有点设计味道,因此请谨慎使用。
您可以让内部接口扩展公共接口,如下所示:
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; }
}
这样你就不需要任何演员或任何东西。
我认为@adrianbanks 的回答可能是对我的改进,但我不认为它真的是(尽管很漂亮)——因为你不能保证传递给你的公共接口实例也实现了内部接口实例——这这个解决方案也是如此。还有一个问题是,它仅在实现类型为internal
- 如果您想提供公共类型作为标准接口实现或作为层次结构的基础时才有效。
这就是我使用的。鉴于:
interface myInterface
{
string myProperty { get; set; }
}
public interface myPublicInterface
{
string myProperty { get; }
}
首先,您不能进行myPublicInterface
继承myInterface
,因为编译器会抱怨不一致的可访问性。因此,您可以使用属性支持者显式地实现内部的,然后隐式地实现公共的:
public class MyClass : myInterface, myPublicInterface
{
private string _myProperty;
string myInterface.myProperty
{
get { return _myProperty; }
set { _myProperty = value; }
}
public string myProperty
{
get { return _myProperty; }
}
}
注意 - 在某些情况下,getter 可能不适合私人支持者,但可能是一些从其他属性计算值的逻辑。在这种情况下——为了保持 DRY——你可以将逻辑放在公共 getter 中,并为显式 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*/ }
}
你可以反过来做,但是你必须对内部接口做一个看起来很糟糕的内联转换:
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; }
}
你应该尽可能地避开它。