2015-12-25 3 views
5

В моих проектах я часто хочу иметь метод (или функцию, если вы предпочитаете), который является приватным, однако я также хочу получить к нему доступ из ОДНОГО другого класса. Возможно ли это?Частный-иш-метод?

Для уточнения этого метода можно получить доступ с ClassA, его собственным классом, но не любым другим.

+2

Если вы поместите оба класса в сборку, предназначенную только для этих двух классов, вы можете использовать 'internal'. Но ... вы можете подумать, зачем вам это нужно. –

+0

Какова рациональность такого дизайна? – dotctor

+0

Возможный дубликат: http://stackoverflow.com/questions/203616/why-does-c-sharp-not-provide-the-c-style-friend-keyword –

ответ

2

Существует множество способов сделать это до вашего последнего утверждения, которое является «и ТОЛЬКО этим классом», я могу только думать об одном способе сделать это, и он должен иметь классы, изложенные в сборках, такие как такие :

Сборка A содержит только класс а с методом, который вы хотите, объявленный как внутренний

Ассамблея B объявлена ​​дружественной сборки: https://msdn.microsoft.com/en-us/library/0tke9fxk.aspx и содержит код для вызова A (он может, как ему это внутреннее, как если бы в тот же сборка, что и сборник)

Никакой другой сборник, связанный с A, B или обоими, не будет быть в состоянии вызвать метод класса А, поскольку он является внутренним.

+0

Я думаю, что это единственный способ сделать это. – dotctor

1

Все, что вы просите, невозможно в C#. Я имею в виду, что нельзя использовать только один класс для использования частного метода. Все, что вы можете сделать, это использовать internal, который позволяет классам только одной сборки обращаться к вашим методам или protected, которые доступны в своем классе и экземплярах производного класса!

Кроме того Существует не эмпирическое правило для того, что вы просите, но вы можете сделать некоторые хак, как показано ниже:

MethodInfo privateMethod = instance.GetType().GetMethod("NameOfPrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance); 
privateMethod.Invoke(instance, new object[] { methodParameters }); 
0

Один немного грязный трюк, чтобы использовать метод из класса B в класс А чтобы сделать метод защищенным, а не частным, и получить A от B.

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

2

Вы можете сделать этот метод защищен, если он подходит для вашей структуры ООП:

public class A 
{ 
    protected void Test() 
    { 
     Console.WriteLine("I can only be called from B"); 
    } 
} 

public class B : A 
{ 
    public void Pub() 
    { 
     Test(); 
    } 
} 

И есть много других способов сделать это.

Однако, в общем, это звучит как неправильный взгляд на модификаторы доступа.
Если вы хотите только вызывать свой метод только с одного места, просто позвоните ему из одного места.
Тот факт, что этот метод следует вызывать из другого класса, делает его общедоступным, логичным и архитектурным.

+0

Каждый класс, полученный из 'A', может получить доступ к методу' Test'. OP хочет «однако я также хочу получить к нему доступ из ОДНОГО другого класса, и только этого другого класса». – dotctor

2

Лучший способ, о котором я могу думать, это.

В C# 5 был добавлен набор атрибутов информации о вызывающем абоненте, а именно [System.Runtime.CompilerServices.CallerMemberName], [System.Runtime.CompilerServices.CallerFilePath] и [System.Runtime.CompilerServices.CallerLineNumber]. Мы можем использовать CallerFilePathAttribute, чтобы узнать, приходит ли вызывающий абонент из определенного файла .cs.

Обычно один файл будет содержать только один класс или структуру. Например, ClassA определен в ClassA.cs. Вы можете проверить, соответствует ли имя файла вызывающего абонента ClassA.cs.

Таким образом изменить параметры вашего метода, как это:

([CallerFilePath] string callerFilePath = "" /*Other parameters*/) 

В методе, проверьте, если callerFilePath соответствует путь к файлу ClassA. Если это не так, напишите исключение, говорящее, что к способу можно получить доступ только от ClassA!

+0

Эта проверка выполняется только во время выполнения. – dotctor

+0

Да ... Я знаю. Но все же вы не можете использовать метод в классе, отличном от класса ClassA. Таким образом, он отвечает требованиям! @dotctor – Sweeper

1

Другим простым способом управления доступом членов является использование делегатов. Давайте предположим, что у вас есть частный метод:

class SecureMethod { 
    private void DoSomething() { } 
} 

Вы можете предоставить доступ к этому методу путем введения делегата этого метода:

class ClassA { 
public ClassA(Action secureMethod) { } 
} 

SecureMethod objWithSecureMethod; 
var a = new ClassA(objWithSecureMethod.DoSomething); 
1

Я показываю вам, как сделать, чтобы это, но это очень плохая практика:

public class A 
{ 
    private void CanOnlyCallMethodInClassB(); 
    public static void SetHandlerCanOnlyCallMethodInClassB(ClassB b) 
    { 
     b.MethodFromClassA = CanOnlyCallMethodInClassB; 
    } 
} 
public class B 
{ 
    public Action MethodFromClassA { get; set; } 
} 

в коде:

var b = new B(); 
A.SetHandlerCanOnlyCallMethodInClassB(b); 
b.MethodFromClassA(); 

но лучше способ использовать объект класса B в классе метода A. Искать google для шаблон стратегии или использовать наследование.