我在程序集 C 中有以下内容:
public interface InterfaceA
{
string Data {get; }
}
public interface InterfaceB
{
InterfaceA DoStuff();
}
public interface InterfaceC
{
IEnumerable<InterfaceA> GetStuffThatHaveBeenDone();
}
InterfaceB 的一个实现称为 Doer,在程序集 A(这是主项目)中定义。 类似地,在 AssemblyA 中定义了 InterfaceA 的实现,但程序集 B 对这些实现一无所知。
程序集 B 将由外部公司开发,并将被程序集 A 引用(不是动态的,在设计时)。该公司的目的是为 InterfaceC 编写一个实现。
情况如下:我想阻止外部公司创建自己的 InterfaceA 实现并将其放入 InterfaceC.GetStuffThatHaveBeenDone() 返回的列表中。预期用法是:它们调用 InterfaceB.DoStuff(),获取 InterfaceA 的实例,并将其添加到它们将返回的列表中。
我必须对 InterfaceC.GetStuffThatHaveBeenDone() 返回的列表中包含的对象的类型做出假设。我知道它们都具有仅在程序集 A 中定义的特定类型。因此,我试图确保这些对象只会在程序集 A 中创建,并且我想在编译时强制执行此操作以避免发现 MyCustomImplementionOfA 对象在列表中。
因此我试图找出如何防止接口在另一个程序集中实现。我想也许可以通过稍微重新考虑我的设计来解决这个问题,但我似乎没有找到。
谢谢你
我喜欢 Eric 提出的不透明代币解决方案。 您还可以通过使用 abstract class 代替
InterfaceA
并将其构造函数设为内部来实现此技巧。
public abstract class ContractA
{
internal ContractA() {};
public abstract string Data {get; }
}
我能想到的唯一方法是创建一个不透明的对象,然后将其传回给他们:
internal interface InterfaceA
{
string Data {get; }
}
public interface InterfaceB
{
OpaqueToken DoStuff();
}
public interface InterfaceC
{
IEnumerable<OpaqueToken> GetStuffThatHaveBeenDone();
}
public sealed class OpaqueToken
{
internal OpaqueToken() {}
internal InterfaceA A { get; set; }
}
这样
InterfaceA
是内部的,因此只有您的库中的代码(除非您使用 InternalsVisibleTo
)才能实现它。您的库的使用者只会看到 OpaqueToken
的实例,并且您的构造函数是内部的,因此他们无法调用它。实现 InterfaceA
的对象也只能在您的库中访问。如果您愿意,OpaqueToken
甚至可以实现InterfaceA
。
需要指出的是,这不是一种安全措施——任何使用反射的消费者都可能违反所有这些规则。
c# 8.0之后,可以使用internal关键字:
public interface IA
{
internal void OnlyImplementableInternal();
}
将接口标记为 internal,然后如果您需要从您自己的任何程序集(例如,不是定义它的程序集)引用该接口,您可以使用 internalsvisibleto 属性来指定哪些程序集可以“看到”它。
以下是您可以执行的操作的提示:
public interface InterfaceA
{
// Only expose what is of public interest!
string Description { get; }
}
internal interface InterfaceAInternal : InterfaceA
{
string Data { get; }
}
public interface InterfaceB
{
InterfaceA DoStuff();
}
internal interface InterfaceC
{
IEnumerable<InterfaceAInternal> GetStuffThatHaveBeenDone();
}
public interface InterfaceD
{
IEnumerable<InterfaceA> GetStuffThatHaveBeenDone();
}
不要注意下面朱哈尔天真的评论。她可能拥有良好的声誉,但这并不是基于真正的编程知识/能力。