C#调用作为接口传递的对象的内部方法

C# Calling internal methods of an object passed as interface

我有一个定义一些函数的接口 IFoo,一个实现 IFoo 和一些内部函数的抽象 class FooBase,以及几个从 FooBase 派生的 classes Foo。
我还有一个 class Bar,它应该从 FooBase 调用一个方法,但它的参数作为 IFoo 传递。所以一切看起来像这样:

public interface IFoo
{
  // Some methods
}

public abstract class FooBase : IFoo
{
  // Methods from IFoo

  internal TInternalType SomeMethod();
}

public class Foo1 : FooBase
{
  // ...
}

public class Bar
{
  public void DoSomething(IFoo foo)
  {
    // This does not feel right:
    TInternalType myT = (foo as FooBase).SomeMethod();
  }
}

如前所述,这感觉不对,因为任何人都可能会出现,写一个 class Baz 实现 IFoo 并用它调用 DoSomething 会失败。

我还发现 this question/solution 与 public 接口的内部问题类似,但这不会改变某些第三方 class 的问题实施 IFoo 会导致问题,即我仍然撒谎 API.

或者我可以更改 DoSomething 的类型以获取 FooBase 类型的参数并通过将构造函数设置为内部来从第三方 class 中保护 FooBase,但我想在我的 [=44] 中只有抽象=] API,不是实现。

所以简而言之,我要问的是:有没有一种方法可以让图书馆只公开抽象(即图书馆的用户只使用那些抽象)但仍然可以访问内部成员?

背景:
我正在编写一个公开某些类型并使用另一个库 L 来实现其功能的库。使用 L 的事实是我想对我的图书馆用户隐藏的一个实现细节,所以在某些时候由于某种原因我必须用其他东西替换 L,我的用户不会注意到。

我现在有一些 Foo classes 将向我的用户公开,还有一个 Bar class 将与 L 一起使用。对于每个 class Foo,一个必须创建来自 L 的 class 的相应实例;但是单独的 Foo classes 太不同了,他们每个人都需要单独的逻辑来创建他们各自的 L class.

这就是为什么我在 FooBase 中定义了一个内部抽象方法,并且每个 Foo 都实现了自己的方法来从 L 生成它的 class,所以 Bar 可以只调用这个方法来获取它需要使用的东西L.

也许存在与内部重载方法完全不同的方法。

如果您想避免向用户公开您的基础 类,为什么不创建另一个派生自 IFoo 的接口,将其命名为 IFooWithSomeMethod,添加一个 SomeMethod 方法,并在 FooBase 中实现该接口?然后 Bar.DoSomething 可以采用 IFooWithSomeMethod 而不是 IFoo.

顺便说一句,很抱歉在第一遍中搞砸了一些名字。希望我现在已经弄清楚了。

如果 FooBase 是一个 特例 (因此您不需要 decalare IFooWithDoSomething)需要额外的调用,您可以实现一个 extension to IFoo, 像这样:

public static class FooExtensions {
  public static void DoSomething(this IFoo value) {
    FooBase special = value as FooBase;

    if (null != special)
      special.SomeMethod();
  }
}

public class Bar
{
  public void DoSomething(IFoo foo)
  {
    // Extension is called
    foo.SomeMethod();
  }
}

接口的全部意义在于展示实现的能力。如果您需要访问实现的内部成员,您应该让代码的使用者知道他们不是真正的内部成员(或者按照这里的其他答案,或者例如 Interface Segregation and passing around only individual role interfaces),或者让他们真正内部.在你的情况下,我认为它应该封装在 FooBase class.

我想 DoSomething 方法也会对 IFoo 实现做其他事情。 Bar 对从内部方法返回的内部类型所做的任何事情都应该在 FooBase 中发生在其他 IFoo 方法之一中。这里的指导原则是 Tell, don't ask.