2010-01-15 75 views
37

我通過繼承RolesService來擴展一個新類。在RolesService中我有一個靜態方法,我想在新派生類中重寫。當我從我的派生對象進行調用時,它不使用重載的靜態方法,它實際上調用基類方法。有任何想法嗎?重寫一個靜態方法

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

我認爲他明白你不能重寫一個靜態方法。他的問題是「任何想法?」在解決這個問題。不知道人們是否意識到這一點,因爲除了Aaronaught之外,所有贊助人都會回答這些問題,而這些答案不包含任何想法。 – 2010-01-15 20:39:39

回答

18

執行以下操作將允許您解決靜態調用問題。當你要使用的代碼通過依賴注入採取IRolesService那麼當你需要MockRolesService你可以通過在

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

現在'IsUserInRole'不再是一個靜態方法。 – Gutblender 2014-08-26 14:00:27

40

您不能覆蓋靜態方法。靜態方法不能是虛擬的,因爲它與類的實例無關。

派生類中的「overriden」方法實際上是一種新方法,與基類中定義的方法無關(因此爲new關鍵字)。

18

您無法重寫靜態方法。

如果你考慮一下,它並沒有什麼意義;爲了有虛擬調度,你需要一個對象的實際實例來檢查。

靜態方法也不能實現接口;如果這個類正在實現一個IRolesService接口,那麼我會認爲這個方法根本不應該是靜態的。有一個實例方法是更好的設計,所以你可以在你準備好時用真實的服務替換你的MockRoleService

12

您無法重寫一個靜態方法。您可能會發現this有趣的閱讀。

0

靜態方法表示與類型本身相關的邏輯。一旦從該類型繼承,父類型的靜態方法就不能被假定爲適用。你可以做的是:

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

在最後一個方法中對IsUserInRole的調用是不明確的,您需要調用MockRoleService.IsUserInRole – 2010-01-15 20:27:52

+0

@Thomas不確定您是在編輯之前還是之後看到代碼,但在當前示例中,對IsUserInRole的調用調用MockRoleService.IsUserInRole。 – 2010-01-15 20:35:51

0

有兩種方式,你可能讓你的模擬對象的工作:

1:更改從RolesService到IRolesService你的父對象的簽名(假設你是不是使用接口已經)。然後將該模擬實現爲IRolesService而不是RolesService。

public class MockRoleService : IRolesService 
{ 
    public new static bool IsUserInRole(string username, string rolename) 
    { 
     return true; 
    } 
} 
  • 依賴注入角色對象。
  • 公共類MockRoleService:RolesService {

    public MockRoleService() 
    { 
        Roles = OverridenRolesObjectThatAlwaysReturnsTrue; 
    } 
    

    }

    2

    爲了調用一個靜態方法,你需要的那種類型的直接引用:

    RolesService.IsUserInRole(...); 
    

    在這種情況下,如果您希望能夠調用「派生」類的靜態方法,請刪除「新」關鍵字wi您可以:

    MockRoleService.IsUserInRole(...); 
    

    並獲得預期的函數調用。

    我的猜測是,這不是你要找的。你可能會在代碼中的某個地方像前一個那樣調用,並且你希望通過使用Mocking工具來創建一個MockRoleService,你會注入這個新的「類型」來代替舊的。不幸的是,這不是它與靜力學的關係。

    一個嘲笑工具將創建一個嘲笑類型的實例,並將注入,而不是一個調用來構造真正的類型。對靜態方法的調用會跳過所有這些。

    正如Aaronaught提到的,您應該使該方法成爲普通的實例方法。這將允許您的模擬服務被正確注入來代替常規的RolesService,允許您將方法聲明移入您的IRolesService接口,並在您的MockRoleService實現中覆蓋它。然後,在你得到一個RolesService的代碼中,你只需調用實例成員而不是靜態成員。

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

    什麼是這樣的:

    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

    我也有類似的問題。我沒有使用繼承或接口,而只是使用委託。

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

    如果你想改變的方法「newMethod」用於測試目的,只需撥打

    RolesService.isUserInRoleFunction = newMethod; 
    
    0

    爲什麼不使用屬性來訪問靜態值?然後它會支持繼承並被覆蓋。這似乎是你在找什麼。

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