2010-01-15 77 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"; 
        } 
    }