C#中的封装和友谊

时间:2011-04-30 11:37:10

标签: c# encapsulation friend

我目前的项目中有一个特例。

我有:

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的派生类)能够执行此操作
  3. 这可能在C#中吗?

    1. 如果可能,该怎么做?
    2. 如果不可能,有哪些替代方案可以尽可能地保护B免于篡改同一个程序集中的类C

6 个答案:

答案 0 :(得分:1)

  

这可能在C#中吗?

不,除非您使用反射:私人和受保护的成员无法从其他类访问。​​

  

如果不可能的话,有哪些替代方案可以尽可能地保护B免受同一组件中C级的篡改?

你可以在B中使B成为嵌套类并使其成为私有。然后你可以安全地增加B的两种方法的可见性,因为只有A才能调用它们(除非使用反射)。

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

“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");
      }

答案 3 :(得分:1)

可以通过发出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 at no cost with coding to interfaces

答案 4 :(得分:0)

  1. 不,它不是(除非你使用反射,但这只是糟糕的设计)
  2. 继承。但即便如此,您也无法调用私有方法。你应该考虑你的设计并加以改进。
  3. 由于您的班级A应该能够在protected上调用B方法,我认为它与它有某种关系。问问自己是否存在“是-a”关系,如“A是B”。在这种情况下,您可以A继承B

    public class A : B
    {
    }
    

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

答案 5 :(得分:0)

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

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

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

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

无法使方法对特定的其他类可见。毕竟,你是那个控制你的程序集中所有类的人,所以你需要确保除了A之外没有其他类调用这些方法。

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