C#中的封装和友谊

本文关键字:友谊 封装 | 更新日期: 2023-09-27 17:53:48

我在当前项目中有一个特殊的案例。

我有:

public class A
{
   // etc.
}
public class B
{
   // etc.
   private void HandleSomeEvent(object parameter)
   {
      // Etc.
   }
   protected void HandleSomeOtherEvent(object parameter)
   {
      // Etc.
   }
}

我想要:

  1. A能够调用私有方法B.HandleSomeEvent,但没有其他类(除了B(能够这样做
  2. A能够调用受保护的方法B.HandleSomeOtherEvent,但没有其他类(除了BB的派生类(能够这样做

这在C#中可能吗?

  1. 如果可能,如何做到这一点
  2. 如果不可能,有什么替代方案可以尽可能保护B不被同一程序集中的类C篡改

C#中的封装和友谊

这在C#中可能吗?

不可以,除非您使用反射:私有成员和受保护成员不能从其他类访问。

如果不可能,有什么替代方案可以尽可能保护B免受同一程序集中的C类的篡改?

您可以将B设为a内部的嵌套类,并将其设为私有类。然后,您可以安全地增加B的两个方法的可见性,因为只有A能够调用它们(除非使用反射(。

这是可能的,但我通常只使用internal,并假设程序集中的其他类表现良好。

例如,您可以将这些方法的委托传递给类A,该类将它们存储在protected static字段/属性中。

"2。如果不可能,有什么替代方案可以尽可能保护B免受同一程序集中的C类的篡改?">

检查调用者的类型信息并抛出异常是否有效?

      [MethodImpl(MethodImplOptions.NoInlining)]  
      private void HandleSomeEvent(object parameter)  
      {  
            StackTrace stackTrace = new StackTrace();
            StackFrame stackFrame = stackTrace.GetFrame(1);
            MethodBase methodBase = stackFrame.GetMethod();
            if(methodBase.DeclaringType == typeof(ClassA)) // Okay.
            else if (methodBase.DeclaringType == typeof(ClassB)) // Okay.
            else throw new ApplicationException("Not Okay");
      }

可以通过发出A的接口,然后将其与具体实现分离。一旦你做到了,你就可以写这样的

interface IA { }
class A : IA
{
    public static IA New() { return new A(); }
    private A() { }
    private void UseB() 
    {  
        var b = new B();
        b.HandleSomeEvent(this, null);
    }
}
class B
{ 
    public void HandleSomeEvent(A onlyAccess, object parameter) { }
}

尽管HandleSomeEvent()是公共的,但只有A可以访问它,因为其他人不可能获得A类的具体实例。它有一个私有构造函数,而工厂New()方法返回一个接口。

请参阅我的文章《Friends and internal interface members with coding to interfaces》,了解详细信息。

您可以将两种方法都标记为internal:

internal void HandleSomeEvent(object parameter)
{
   // Etc.
}
protected internal void HandleSomeOtherEvent(object parameter)
{
   // Etc.
}

这使得这两个方法对同一程序集中的所有类都可见(第二个方法对从B派生的所有类也可见(。

没有办法使方法对特定的其他类可见。毕竟,您是控制程序集中所有类的人,所以您应该确保除了A之外没有其他类调用这些方法。

如果你真的需要工具的帮助,你可以编写一个FxCop规则,或者创建某种后构建的操作,检查来自A以外的其他类的方法调用。

  1. 不,它不是(除非你使用反射,但这只是糟糕的设计(
  2. 继承。但即便如此,您也无法调用私有方法。你应该考虑一下你的设计并加以改进

由于你的类A应该能够在B上调用protected方法,我认为它与之有某种关系。问问自己是否存在"is-a"关系,比如"a是B"。在这种情况下,您可以使A继承自B:

public class A : B
{
}

现在,您可以在B上调用受保护的方法。但请不要只是继承,要经常问问自己继承是否有意义。