c# - profesor - Método de límite para que solo sea llamado por una clase particular
superprof colombia (4)
Está en contra de las mejores prácticas de OOP para hacer tal diseño. Los métodos de clases no deben estar protegidos de ser llamados.
Si su diseño requiere control sobre la llamada a un método, entonces el control debe ejercerse probando los argumentos: el llamante que está autorizado para hacer una llamada "sabría" la palabra mágica para pasar como el argumento.
Quiero que un método particular en una clase solo sea accesible por una clase particular. Por ejemplo:
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
}
}
¿Hay alguna palabra clave o atributo que pueda usar para imponer esto?
ACTUALIZAR:
Debido a la complejidad del sistema existente y las limitaciones de tiempo, necesitaba una solución de bajo impacto. Y quería algo que me indicara en el momento de la compilación que no se podía utilizar LimitedAccess (). Confío en la respuesta de Jon Skeet de que exactamente lo que pedí no se pudo hacer en C #.
La pregunta y la respuesta de Jon son buenas para quienes puedan encontrar esto más adelante. Y el hecho de que este diseño huele puede desviar a cualquiera para elegir algo como esto como una solución deseada.
Como se mencionó en un comentario, la conversación con un amigo de C # es útil si estás tratando de resolver una situación similar.
En cuanto a mi solución particular: "por qué A contendría la lógica de B" (preguntado por @sysexpand en los comentarios). Ese es el problema. B.Func()
fue llamado en todo el sistema en el que estoy trabajando, pero operaba principalmente en un singleton de A
Entonces, lo que terminé haciendo fue mover B
(s) Func()
a A
y hacer que A.LimitedAccess()
privado. Hubo algunos otros detalles para solucionar, como siempre, pero obtuve una solución de bajo impacto que me dio errores de compilación en las personas que llamaban a A.LimitedAccess()
.
Gracias por la discusión.
No. Lo único que podría hacer sería convertir el LimitedAccess
un método privado y anidar la clase B
dentro de la clase A
(Supongo que desea que todas las clases estén en el mismo ensamblaje. De lo contrario, podría colocar A
y B
en el mismo ensamblaje, y C
en un ensamblaje diferente, y convertir el LimitedAccess
un método internal
).
Suponiendo que solo desea restringir el acceso a métodos y variables para una instancia específica , puede lograr este efecto utilizando una interfaz. Sin embargo, no impide que alguien cree su propia instancia de la clase, momento en el que tendrán acceso completo a esa instancia.
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();
}
}
Tal vez esto es una solución.
Use System.Runtime.CompilerServices y luego puede verificar el Nombre de la función de llamada y / o el archivo, en el que se define la función de llamada. Si tiene una clase por archivo, el nombre del archivo podría ser una subactividad para el nombre de la clase. Compruébalo y bloquea la llamada.
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
}