2010-01-15 23 views
37

Ich erweitere eine neue Klasse, indem ich von RolesService erbte. In RolesService habe ich ein statisches Verfahren, das ich in meiner neu abgeleiteten Klasse überschreiben möchte. Wenn ich den Aufruf von meinem abgeleiteten Objekt mache, verwendet er nicht die überschriebene statische Methode, sondern ruft tatsächlich die Basisklassenmethode auf. Irgendwelche Ideen?Eine statische Methode überschreiben

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

Ich denke, er versteht, dass Sie eine statische Methode nicht überschreiben können. Seine Frage ist "Irgendwelche Ideen?" um das zu umgehen. Ich bin mir nicht sicher, ob die Leute das merken, weil alle Upvotes zu Antworten gehen, die keine Ideen enthalten, um das zu umgehen, außer für Aaronaught. –

Antwort

18

Durch folgende Schritte können Sie den statischen Aufruf umgehen. Wo Sie den Code nehmen eine IRolesService über Dependency Injection dann verwenden möchten, wenn Sie MockRolesService benötigen, können Sie das in geben

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

Jetzt ist "IsUserInRole" keine statische Methode mehr. – Gutblender

40

Sie können eine statische Methode nicht überschreiben. Eine statische Methode kann nicht virtuell sein, da sie sich nicht auf eine Instanz der Klasse bezieht.

Die Methode "overriden" in der abgeleiteten Klasse ist eigentlich eine neue Methode, die nicht mit der in der Basisklasse definierten Methode in Zusammenhang steht (daher das Schlüsselwort new).

18

Sie können eine statische Methode nicht überschreiben.

Wenn Sie darüber nachdenken, macht es keinen Sinn; Um einen virtuellen Versand zu haben, benötigen Sie eine tatsächliche Instanz eines Objekts, gegen das geprüft werden soll.

Eine statische Methode kann auch keine Schnittstelle implementieren; Wenn diese Klasse eine IRolesService Schnittstelle implementiert, würde ich behaupten, dass die Methode überhaupt nicht statisch sein sollte. Es ist besser, eine Instanzmethode zu verwenden, so dass Sie Ihre MockRoleService mit einem echten Service austauschen können, wenn Sie fertig sind.

12

Sie können eine statische Methode nicht überschreiben. Sie könnten this eine interessante lesen finden.

0

Eine statische Methode stellt die Logik dar, die für den Typ selbst relevant ist. Sobald Sie von diesem Typ erben, kann nicht davon ausgegangen werden, dass die statischen Methoden des übergeordneten Typs gelten. Was Sie tun können, ist die folgende:

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

Der Aufruf von IsUserInRole in der letzten Methode ist mehrdeutig, müssen Sie MockRoleService.IsUserInRole aufrufen –

+0

@Thomas nicht sicher, ob Sie den Code vor oder nach meiner Bearbeitung gesehen, aber im aktuellen Beispiel ruft der Aufruf von IsUserInRole MockRoleService.IsUserInRole. –

0

Es gibt zwei Möglichkeiten, wie Sie vielleicht Ihr Mock-Objekt Arbeit machen:

1: Ändern Sie die Signatur Ihrer Eltern-Objekt von RolesService zu IRolesService (vorausgesetzt, Sie sind nicht Benutzung der Schnittstelle bereits). Implementieren Sie dann den Schein zu IRolesService anstelle von RolesService.

public class MockRoleService : IRolesService 
{ 
    public new static bool IsUserInRole(string username, string rolename) 
    { 
     return true; 
    } 
} 
  1. Abhängigkeit injizieren die Rollen Objekt.

public class MockRoleService: RolesService {

public MockRoleService() 
{ 
    Roles = OverridenRolesObjectThatAlwaysReturnsTrue; 
} 

}

2

Um eine statische Methode aufrufen, müssen Sie eine direkte Referenz des Typs:

RolesService.IsUserInRole(...); 

Wenn Sie in der Lage sein und die statische Methode der "abgeleiteten" Klasse aufrufen möchten, löschen Sie das "neue" Schlüsselwort wi ll ermöglichen Ihnen:

MockRoleService.IsUserInRole(...); 

und erhalten Sie den erwarteten Funktionsaufruf.

Meine Vermutung ist, dass dies nicht das ist, wonach Sie suchen. Sie haben wahrscheinlich irgendwo in Ihrem Code einen Anruf wie der erste, und Sie hoffen, dass Sie mit diesem Mocking-Tool einen neuen "Typ" anstelle des alten eingeben würden, um einen MockRoleService zu erstellen.Leider funktioniert das nicht mit Statik.

Ein Mock-Tool wird eine Instanz des Might-Out-Typs erstellen und diese anstelle eines Aufrufs injizieren, um den Realtyp zu erstellen. Ein Aufruf an eine statische Methode überspringt das alles.

Wie Aaronaught erwähnt, sollten Sie diese Methode wahrscheinlich zu einer normalen Instanzmethode machen. Dies würde ermöglichen, dass Ihr Scheindienst anstelle des regulären RolesService ordnungsgemäß eingefügt wird. Sie können die Methodendeklaration in Ihre IRolesService-Schnittstelle verschieben und in Ihrer MockRoleService-Implementierung überschreiben. Dann rufen Sie in dem Code, in dem Sie einen RolesService erhalten, nur das Instance-Member anstelle des Static-Members auf.

2

Was ist so etwas wie dieses:.

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

Ich hatte ein ähnliches Problem. Ich habe keine Vererbung oder eine Schnittstelle verwendet, sondern einfach einen Delegaten verwendet.

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); 
     } 
    } 

Wenn Sie möchten, um die Methode ändern, um „newMethod“ für Testzwecke, rufen Sie einfach

RolesService.isUserInRoleFunction = newMethod; 
0

Warum den statischen Wert nicht eine Eigenschaft zuzugreifen? Dann würde es die Vererbung unterstützen und übersteuerbar sein. Was genau das zu sein scheint, wonach Sie suchen.

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

    public string MyStaticMethod() { 
     return "Example"; 
    } 
} 
Verwandte Themen