关于c#:limit方法只能由特定类调用


limit method to only be called by a particular class

我希望一个类中的特定方法只能由特定的类访问。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class A
{
  public void LimitedAccess() {}
  public void FullAccess() {}
}

public class B
{
  public void Func()
  {
     A a = new A();
     a.LimitedAccess();       // want to be able to call this only from class B
  }
}

public class C
{
  public void Func()
  {
     A a = new A();
     a.FullAccess();           // want to be able to call this method
     a.LimitedAccess();        // but want this to fail compile
  }
}

是否有关键字或属性可用于强制执行此操作?

更新:

由于现有的系统复杂性和时间限制,我需要一个低影响的解决方案。我想在编译时指出limitedaccess()不能使用。我相信乔恩·斯基特的回答,我所要求的不能用C语言完成。

这个问题和乔恩的回答对那些稍后可能遇到这个问题的人来说是好的。事实上,这种设计的气味可能会让任何人选择像这样的东西作为理想的解决方案。

正如在评论中提到的,如果你试图解决类似的情况,c朋友的对话是有用的阅读。

至于我的特定解决方案:"为什么a包含b的逻辑"(由@sysexpand在注释中提出)。这就是问题所在。我正在研究的整个系统中都调用了B.Func(),但它主要是在一个单独的A上运行的。所以我最后做的是把BFunc()转移到A中,使A.LimitedAccess()私有化。还有一些其他的细节需要解决,就像以前一样,但是我得到了一个低影响的解决方案,它给了我在A.LimitedAccess()的调用者上的编译时错误。

谢谢你的讨论。


不,您唯一能做的就是使LimitedAccess成为私有方法,并将类B嵌套在类A中。

(我假设您希望所有类都在同一程序集中。否则,可以把AB放在同一个组件中,把C放在不同的组件中,使LimitedAccess成为internal方法。)


假设您只想限制对特定实例的方法和变量的访问,那么可以通过使用接口来实现这种效果。但是,它不会阻止某人创建自己的类实例,此时他们将拥有对该实例的完全访问权。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public interface IA
{
  void FullAccess();
}


public class A : IA
{
  public void LimitedAccess() {}  //does not implement any interface
  public void FullAccess() {}     //implements interface
}


public class B
{
  private A a = new A();

  public IA GetA()
  {
    return (IA)a;
  }

  public void Func()
  {
     /* will be able to call LimitedAccess only from class B,
        as long as everybody else only has a reference to the interface (IA). */

     a.LimitedAccess();      
  }
}


//This represents all other classes
public class C
{
  public IA Ia;

  public void Func()
  {
     Ia.FullAccess();           // will be able to call this method
     Ia.LimitedAccess();        // this will fail compile
  }
}

public static class MainClass
{
  static void Main(string[] args)
  {
    B b = new B();
    b.Func();
    C c = new C();
    c.Ia = b.GetA();
    c.Func();
  }
}


也许这是一个解决办法。

使用system.runtime.compilerservices,然后可以检查调用函数的名称和/或定义调用函数的文件。如果每个文件都有一个类,则文件名可能是类名的替换项。检查并阻止呼叫。

1
2
3
4
5
6
7
8
internal void MySecretFunction (string something,
  [CallerMemberName] string memberName = null,
  [CallerFilePath] string filePath = null,
  [CallerLineNumber] int lineNumber = 0) {
    if (!filePath.EndsWith(@"\goodClass.cs")) return;

    // else do something
}

这样的设计不符合OOP最佳实践。不应保护类的方法不被调用。

如果您的设计需要对调用方法进行控制,那么应该通过测试参数来进行控制-授权进行调用的调用方将"知道"要作为参数传递的魔力词。