2010-01-15 20 views
37

Estoy extendiendo una nueva clase al heredar de RolesService. En RolesService tengo un methog estático que me gustaría anular en mi nueva clase derivada. Cuando realizo la llamada desde mi objeto derivado, no utiliza el método estático anulado, realmente llama al método de clase base. ¿Algunas ideas?Anular un método estático

public class RolesService : IRolesService 
{ 
    public static bool IsUserInRole(string username, string rolename) 
    { 
     return Roles.IsUserInRole(username, rolename); 
    } 
} 

public class MockRoleService : RolesService 
{ 
    public new static bool IsUserInRole(string username, string rolename) 
    { 
     return true; 
    } 
} 
+5

Creo que entiende que no puede anular un método estático. Su pregunta es "¿Alguna idea?" para sortear eso No estoy seguro si la gente se da cuenta de esto, ya que todos los votos a favor van a las respuestas que no contienen ninguna idea para evitarlo, a excepción de Aaronaught. –

Respuesta

18

la siguiente manera el se permitirá trabajar en torno a la llamada estática. En la que desea utilizar el código de tomar una IRolesService a través de la inyección de dependencia a continuación, cuando se necesita MockRolesService puede pasar que en

public interface IRolesService 
{ 
    bool IsUserInRole(string username, string rolename); 
} 

public class RolesService : IRolesService 
{ 
    public bool IsUserInRole(string username, string rolename) 
    { 
     return Roles.IsUserInRole(username, rolename); 
    } 
} 

public class MockRoleService : IRolesService 
{ 
    public bool IsUserInRole(string username, string rolename) 
    { 
     return true; 
    } 
} 
+19

Ahora 'IsUserInRole' ya no es un método estático. – Gutblender

40

No puede anular un método estático. Un método estático no puede ser virtual, ya que no está relacionado con una instancia de la clase.

El método "anulado" en la clase derivada es en realidad un método nuevo, no relacionado con el definido en la clase base (de ahí la palabra clave new).

18

No puede anular un método estático.

Si lo piensas bien, en realidad no tiene sentido; para tener un despacho virtual necesitas una instancia real de un objeto para verificar.

Un método estático tampoco puede implementar una interfaz; si esta clase implementa una interfaz IRolesService, yo diría que el método no debe ser estático. Es mejor diseñar un método de instancia, por lo que puede cambiar su MockRoleService con un servicio real cuando esté listo.

12

No puede anular un método estático. Puede encontrar this una lectura interesante.

0

Un método estático representa la lógica pertinente para el tipo en sí. Una vez que herede de ese tipo, no se puede suponer que se apliquen los métodos estáticos del tipo principal. Lo que puede hacer es la siguiente:

public class RolesService : IRolesService 
{ 
    public static bool IsUserInRole(string username, string rolename) 
    { 
     return Roles.IsUserInRole(username, rolename); 
    } 

    // call this guy within the class 
    protected virtual bool DoIsUserInRole(string username, string rolename) 
    { 
     return IsUserInRole(username, rolename); 
    } 
} 

public class MockRoleService : RolesService 
{ 
    public new static bool IsUserInRole(string username, string rolename) 
    { 
     return true; 
    } 

    protected override bool DoIsUserInRole(string username, string rolename) 
    { 
     return IsUserInRole(username, rolename); // invokes MockRoleService.IsUserInRole 

     // or simply 
     return true; 
    } 
} 
+0

La llamada a IsUserInRole en el último método es ambigua, debe llamar a MockRoleService.IsUserInRole –

+0

@Thomas no estoy seguro de si vio el código antes o después de mi edición, pero en la muestra actual, la llamada a IsUserInRole invoca MockRoleService.IsUserInRole. –

0

Hay dos formas en las que pueden hacer que el objeto de burla:

1: Cambiar la firma de su objeto padre de RolesService a IRolesService (asumiendo que no están usando la interfaz ya). Luego implemente el simulacro a IRolesService en lugar de RolesService.

public class MockRoleService : IRolesService 
{ 
    public new static bool IsUserInRole(string username, string rolename) 
    { 
     return true; 
    } 
} 
  1. Dependencia inyectar objeto los Roles.

MockRoleService clase pública: RolesService {

public MockRoleService() 
{ 
    Roles = OverridenRolesObjectThatAlwaysReturnsTrue; 
} 

}

2

Con el fin de llamar a un método estático, necesitará una referencia directa del tipo:

RolesService.IsUserInRole(...); 

En cuyo caso, si desea poder y llamar al método estático de la clase "derivada", soltar la palabra clave "nueva" wi ll le permitirá:

MockRoleService.IsUserInRole(...); 

y obtener la llamada a la función esperada.

Supongo que esto no es lo que estás buscando. Es probable que tengas alguna llamada en algún lugar de tu código como la primera, y esperas que al usar una herramienta de burlarse para crear un MockRoleService, estarías inyectando este nuevo "tipo" en lugar del anterior.Lamentablemente, no es así como funciona con la estática.

Una herramienta de burlarse creará una instancia del tipo burlado e inyectará eso en lugar de una llamada para construir el tipo real. Una llamada a un método estático omite todo eso.

Como mencionó Aaronaught, probablemente debas hacer de este método un método de instancia normal. Esto permitiría que su servicio simulado sea inyectado adecuadamente en lugar de su RolesService normal, le permitirá mover la declaración del método a su interfaz IRolesService y anularla en su implementación de MockRoleService. Luego, en el código donde "obtienes" un RolesService, solo llamas al miembro de la instancia en lugar de a la estática.

IRolesService svc = MyServiceInjector.GetService<IRolesService>(); 
svc.IsUserInRole(...); 
2

¿Qué pasa algo como esto:.

public interface IRolesService 
{ 
    bool IsUserInRoleImpl(string username, string rolename); 
} 

public abstract class RolesServiceBase<T> where T : IRolesService, new() 
{ 
    protected static T rolesService = new T(); 

    public static bool IsUserInRole(string username, string rolename) 
    { 
     return rolesService.IsUserInRoleImpl(username, rolename); 
    } 
} 

public class RolesService : RolesServiceBase<RolesService>, IRolesService 
{ 
    public bool IsUserInRoleImpl(string username, string rolename) 
    { 
     return Roles.IsUserInRole(username, rolename); 
    } 
} 

public class MockRoleService : RolesServiceBase<MockRoleService>, IRolesService 
{ 
    public bool IsUserInRoleImpl(string username, string rolename) 
    { 
     return true; 
    } 
} 
2

que tenía un problema similar. No usé herencia o una interfaz, sino que simplemente usé un delegado.

public class RolesService 
    { 
     static RolesService() 
     { 
      isUserInRoleFunction = IsUserInRole; 
     } 

     public static delegate bool IsUserInRoleFunctionDelegate(string username, string rolename); 

     public static IsUserInRoleFunctionDelegate isUserInRoleFunction { get; set; } 

     private bool IsUserInRole(string username, string rolename) 
     { 
      return Roles.IsUserInRole(username, rolename); 
     } 
    } 

Si desea cambiar el método de "newMethod" para propósitos de prueba, a llamar a

RolesService.isUserInRoleFunction = newMethod; 
0

por qué no utilizar una propiedad para acceder al valor estático? Entonces apoyaría la herencia y sería invalidable. Que parece ser lo que estás buscando.

public class StaticOverride { 
    public virtual string MyVal { get { return MyStaticMethod(); } } 

    public string MyStaticMethod() { 
     return "Example"; 
    } 
} 
Cuestiones relacionadas