Как запретить вызов метода C # - PullRequest
14 голосов
/ 15 января 2010

Я хочу разрешить вызов метода только из определенных методов. Посмотрите на код ниже.

  private static void TargetMethod()
  {
  }

  private static void ForbiddenMethod()
  {
     TargetMethod();
  }

  private static void AllowedMethod()
  {
     TargetMethod();
  }

Мне нужно, чтобы только AllowedMethod мог вызывать TargetMethod. Как это сделать с помощью классов из System.Security.Permissions?

Обновлено: Спасибо за ваши ответы, но я не хочу спорить о дизайне моего приложения. Я просто хочу знать, возможно ли это сделать с помощью .net security или нет?

Ответы [ 7 ]

24 голосов
/ 15 января 2010

Вы можете решить эту проблему, используя обычный объектно-ориентированный дизайн. Переместите AllowedMethod в новый класс и сделайте ForbiddenMethod закрытым методом этого класса:

public class MyClass
{
    public void AllowedMethod() { // ... }

    private void TargetMethod() { // ... }
}

AllowedMethod имеет доступ к закрытым членам, но никто другой не имеет.

8 голосов
/ 15 января 2010

Я считаю, что вы должны попытаться структурировать свой код в значимых классах и использовать стандартные модификаторы доступа (private, protected, public, internal). Есть ли какая-то конкретная причина, по которой это не решило бы вашу проблему?

Единственная альтернатива, о которой я могу подумать, - это обход стека вызовов из вызываемого абонента, но это, вероятно, приведет к путанице в коде и неоптимальной производительности.

6 голосов
/ 15 января 2010

Вы можете проверить стек вызовов, чтобы выполнить это, но это довольно медленно. Я не рекомендовал бы это, если этого можно избежать.

Если вы все еще хотите это сделать, вам следует быть осторожным, чтобы избежать встраивания методов, иначе ваш код может внезапно перестать работать при сборках Release.

[MethodImpl(MethodImplOptions.NoInlining)]
private static void TargetMethod()
{
    StackFrame fr = new StackFrame(1, false);
    Console.WriteLine(fr.GetMethod().Name);
}

Насколько я знаю, для этого нет готовых атрибутов.

4 голосов
/ 15 января 2010

CAS не может сделать это, если код выполняется с полным доверием.

Если код выполняется в режиме полного доверия (то есть обычное локальное приложение, а не приложение silverlight или что-то запускаемое из сети), то все проверки .NET CAS полностью игнорируются; любой атрибут безопасности просто игнорируется.

CAS просто обходит стек, чтобы определить разрешения, и вы можете сделать это тоже, как указывал ранее Дарин, просто проверив StackTrace.

4 голосов
/ 15 января 2010

Я не уверен, что это достижимо с System.Security.Permissions, но внутри TargetMethod вы можете получить вызывающего абонента и действовать соответственно:

StackTrace stackTrace = new StackTrace();
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
3 голосов
/ 15 января 2010

Возможно, вы сможете использовать объекты CodeAccessPermission. Вы должны будете реализовать интерфейс в своем собственном объекте, чтобы он работал так, как вы предлагаете.

http://msdn.microsoft.com/en-us/library/system.security.codeaccesspermission.aspx

2 голосов
/ 15 января 2010

С помощью атрибутов вы можете решить эту проблему.

Использовать условные атрибуты.

В топе

#define "Show" 


  public void TargetMethod()
    {
      //Code
    }
   [ Conditional("Hidden")]
   public void HiddenMethod()
    {
       TargetMethod()
    }
 [ Conditional("Show")]
  public void AllowMethod()
    {
       TargetMethod()
    }

Будет назван один из ваших методов.

...