如何定义'public'和& # 39;私人# 39;对象的接口

本文关键字:私人 接口 对象 定义 何定义 public | 更新日期: 2023-09-27 17:48:57

我有一个数据库和一个DAL类,它以类似实体框架的方式管理对象到数据(反之亦然)的映射——但我们还不能在这里使用EF,所以DAL是一个相当简单的自成库,它公开了一些对象,并允许对它们执行操作。它是有效的,直到我们找到一个"合适的"EF解决方案。

DAL为"客户端"应用程序提供了各种各样的对象,定义了方法和属性来封装每个操作的逻辑,隐藏这些对象的内部状态以及将它们持久化到数据库所需的机制。

然而,有一些操作是由DALs的对象接口公开的,这些操作实际上应该是"私有的"——它们被运行在其他地方的服务应用程序使用,对数据库中的对象做各种后台工作。我并不是真的希望"客户端"应用程序能够看到这些方法,但是我确实希望当服务应用程序引用DAL时,这些方法是可见的。

当前实现的示例:

DAL Library
  Object
    Method LoadObject()
    Method SaveObject()
    Method AdjustInternalObjectProperty()

因此,客户端应用程序可以看到所有三个方法,尽管它们永远不应该使用第三个方法——第三个方法应该只对服务应用程序可见(它应该能够看到并使用所有三个方法)。

所以问题是,最好的方法是什么,它将保留使用每个对象的接口的意图,但它将"隐藏"该接口的部分,只使隐藏的部分访问一个适当的"友好"的服务应用程序。是否有一些访问修饰器技术,让我使接口的某些部分"私有",与机制,服务应用程序使用(但客户端不)获得访问那些私有元素?或者这是一个应该存在两个不同接口的场景,其中"客户端"接口只是省略了"内部"方法?还是别的什么?

我想以"正确"的方式做到这一点——我已经搜索了SO,并找到了一堆关于多个对象接口的回答问题,但似乎没有一个非常适合我的具体问题。如果存在的答案,请务必指出它并结束这个问题。

编辑(阅读答案并实验后):

using System;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Test")]
namespace Interface_Test
{
  public interface IStandard
  {
    void StandardMethod();
  }
  internal interface ISuper : IStandard
  {
    void SuperMethod();
  }
  public sealed class TestClass : ISuper
  {
    public void StandardMethod()
    {
      Console.WriteLine("The standard method");
    }
    void ISuper.SuperMethod()
    {
      Console.WriteLine("The super method");
    }
  }
}

这就完成了任务——大部分对象是通过IStandard接口公开的,这是一个标准的公共接口,任何和所有客户端程序集都可以使用。"受限"的东西只能通过备用ISuper接口访问,它继承了IStandard的所有核心内容,但增加了我只希望特定"服务客户端"使用的额外项目。通过按照建议添加[InternalsVisibleTo]属性,这个接口和它的方法/属性对除了命名程序集之外的所有人都是完全不可见的。

缺点是有两个接口,但是在没有语言设施(如允许'internal'作为接口方法定义的修饰符)的情况下,这是确保客户端程序集不能获得接口支持但不用于一般用途的功能的合理方法。

如何定义'public'和& # 39;私人# 39;对象的接口

一个选项是:

    创建internal接口
  • 显式地实现(避免需要公共方法)
  • 使用[InternalsVisibleTo]让你的"服务应用程序"访问内部接口

你可能会对这篇博客文章感兴趣,它展示了一些其他情况下有趣的选项

一种常见的方法是有两个接口:

public interface IBar
{
   void DoSimpleStudd();
   int This {get;}
}
public interface ISuperBar : IBar
{
   void DoComplexStuff();
   int That {get; set;}
}
// at service layer
public class ServiceWidget
{
    public ISuperBar Bar {get; set;}
    ...
}
// other places
public class ServiceWidget
{
    public IBar Bar {get; set;}
    ...
}

所以在service layer中,他们将使用ISuperBar,而在应用程序的其他部分,他们将使用IBar

更新