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

本文关键字:对象 内部 方法 调用 接口 | 更新日期: 2023-09-27 18:37:17

我有一个定义一些函数的接口IFoo,一个实现IFoo和一些内部函数的抽象类FooBase,以及几个从FooBase派生的Foo类。
我还有一个类 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();
  }
}

如前所述,这感觉不对,因为任何人都可以来,编写一个实现IFoo的类Baz,并用它调用DoSomething将失败。

我还发现了这个问题/解决方案,以解决有关公共接口的内部内容的类似问题,但这不会改变某些实现 IFoo 的第三方类会导致问题的问题,即我仍然有一个说谎的 API。

或者,我可以更改 DoSomething 的类型以采用 FooBase 类型的参数,并通过使构造函数成为内部构造函数来保护 FooBase 免受第三方类的影响,但我只想在我的公共 API 中具有抽象,而不是实现。

简而言之,我要问:有没有办法让库只公开抽象(即库的用户只使用这些抽象)但仍然访问内部成员?

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

我现在有一些 Foo 类将公开给我的用户,还有一个 Bar 类将与 L 一起使用。对于每个类 Foo,必须从 L 创建一个类的相应实例;但是单独的 Foo 类差异太大,它们都需要单独的逻辑来创建各自的 L 类。

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

也许有一种与内部重载方法完全不同的方法。

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

如果你想

避免向用户公开你的基类,为什么不创建另一个从IFoo派生的接口,称之为类似IFooWithSomeMethod,添加一个SomeMethod方法,并在FooBase中实现该接口? 然后Bar.DoSomething可以采取IFooWithSomeMethod而不是IFoo.

顺便说一句,很抱歉在第一遍中搞砸了一些名字。 希望我现在把一切都理顺了。

接口的全部意义在于展示实现的能力。如果需要访问实现的内部成员,则应让代码的使用者知道它们不是真正的内部成员(通过遵循此处的其他答案,或者例如使用接口隔离并仅传递单个角色接口),或者将它们保留为真正的内部成员。在您的情况下,我认为它应该封装在FooBase类中。

我想 DoSomething 方法也会对IFoo实现做其他事情。无论Bar对从内部方法返回的内部类型执行什么操作,都可能FooBase发生在其他IFoo方法之一中。这里的指导原则是告诉,不要问

如果FooBase是一个特殊情况(所以你不想要decalare IFooWithDoSomething),需要额外的调用,你可以实现一个扩展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();
  }
}