C# 中的封装和友谊

发布于 2024-11-04 09:20:53 字数 653 浏览 2 评论 0原文

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

我有:

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 的篡改?

I have a particular case in my current project.

I have:

public class A
{
   // etc.
}

public class B
{
   // etc.

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

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

I want:

  1. A to be able to call the private method B.HandleSomeEvent, but no other class (but B) to be able to do that
  2. A to be able to call the protected method B.HandleSomeOtherEvent, but no other class (but B and B's derived classes) to be able to do that

Is that possible in C# ?

  1. If possible, how to do that?
  2. If not possible, what are the alternatives which can protect B as much as possible from tampering from, say, a class C in the same assembly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

小…红帽 2024-11-11 09:20:53

这在 C# 中可能吗?

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

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

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

Is that possible in C# ?

No, unless you use reflection: private and protected members are not accessible from other classes.

If not possible, what are the alternatives which can protect B as much as possible from tampering from, say, a class C in the same assembly?

You could make B a nested class inside A and make it private. Then you can safely increase the visibility of the two methods of B as only A will be able to call them (unless reflection is used).

沙沙粒小 2024-11-11 09:20:53

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

例如,您可以将这些方法的委托传递给类 A,类 A 将它们存储在受保护的静态字段/属性中。

It is possible, but I'd usually just go with internal and assume that other classes in the assembly are well behaved.

You could for example pass delegates to these methods to class A which stores them in protected static fields/properties.

梦太阳 2024-11-11 09:20:53

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

"2. If not possible, what are the alternatives which can protect B as much as possible from tampering from, say, a class C in the same assembly?"

Would checking the type info of the caller and throwing an exception work?

      [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");
      }
酒绊 2024-11-11 09:20:53

可以通过发出 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() 方法返回一个接口。

请参阅我的文章好友和内部界面成员,网址为接口编码无需任何成本了解详细信息。

It is possible by emitting an interface of A then separating it from a concrete implementation. Once you did it you can write something like this

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) { }
}

In spite of the fact that HandleSomeEvent() is public only A can access it, since no one else can possibly get a concrete instance of A class. It has a private constructor, while the factory New() method returns an interface.

See my article Friends and internal interface members at no cost with coding to interfaces for details.

维持三分热 2024-11-11 09:20:53

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

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

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

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

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

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

You can mark both methods as internal:

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

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

This makes the two methods visible to all classes in the same assembly (and also the second method visible to all classes derived from B).

There is no way to make a method visible to a specific other class. After all, you're the one who's controlling all classes in your assembly, so it's up to you to make sure that no other class than A calls the methods.

If you really need help from a tool with this, you could write an FxCop rule or create some kind of post-built action that checks for method calls from other classes than A.

小苏打饼 2024-11-11 09:20:53
  1. 不,它不是(除非您使用反射,但这只是糟糕的设计)
  2. 继承。但即便如此,您也无法调用私有方法。您应该考虑您的设计并改进它。

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

public class A : B
{
}

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

  1. No, it isn't (unless you use reflection, but that's just bad design)
  2. Inheritance. But even then you won't be able to call the private method. You should think about your design and improve it.

As your class A should be able to call protected methods on B, I figure it has some sort of relationship with it. Ask yourself if there is a "is-a" relationship, as in "A is a B". In this case, you can make A inherit from B:

public class A : B
{
}

Now, you are able to call protected methods on B. But please, don't just inherit, always ask yourself if the inheritance makes sense.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文