如何定义对象的“公共”和“私有”接口?

时间:2011-04-04 11:43:21

标签: c# interface

我有一个数据库和一个DAL类,它以与实体框架类似的方式管理对象到数据(反之亦然)映射 - 但我们还不能在这里使用EF,所以DAL是一个相当的简单的本土库,它暴露了一些对象并允许对它们执行操作。它可以工作,直到我们可以使用“正确的”EF解决方案。

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

但是,DAL的对象接口所暴露的某些操作应该是“私有的” - 它们由在其他地方运行的服务应用程序使用,为数据库中的对象执行各种后台操作。我真的不希望'客户'应用程序能够看到这些方法,但我希望在服务应用程序引用DAL时可以看到这些方法。

当前实施的示例:

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

因此,客户端应用程序可以看到所有这三种方法,但它们永远不应该使用第三种方法 - 这是一个只应该对服务应用程序可见的功能(应该能够查看和使用所有这三种方法)。 / p>

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

我想以'正确'的方式做到这一点 - 我搜索了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'作为接口方法定义的修饰符,这是确保客户端程序集无法获得功能的合理方法接口支持,但不适用于一般用途。

2 个答案:

答案 0 :(得分:4)

一个选项是:

  • 创建internal界面
  • 明确实施(以避免需要公共方法)
  • 使用[InternalsVisibleTo]为您的“服务应用程序”提供对内部界面的访问权

您可能会对this blog post感兴趣,这会为其他情况显示一些有趣的选项。

答案 1 :(得分:3)

一种常见方法是拥有2个接口:

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

更新

是的,界面是公开的。