C# 重写静态方法

C# 重写静态方法,c#,asp.net,asp.net-mvc,C#,Asp.net,Asp.net Mvc,我通过继承RoleService扩展了一个新类。在RoleService中,我有一个静态方法,我希望在新派生的类中重写它。当我从派生对象进行调用时,它不使用重写的静态方法,而是实际调用基类方法。有什么想法吗 public class RolesService : IRolesService { public static bool IsUserInRole(string username, string rolename) { return Roles.IsUse

我通过继承RoleService扩展了一个新类。在RoleService中,我有一个静态方法,我希望在新派生的类中重写它。当我从派生对象进行调用时,它不使用重写的静态方法,而是实际调用基类方法。有什么想法吗

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

不能重写静态方法。静态方法不能是虚拟的,因为它与类的实例无关


派生类中的“重写”方法实际上是一个新方法,与基类中定义的方法无关(因此使用
new
关键字)。

不能重写静态方法

如果你想一想,那就没什么意义了;为了进行虚拟分派,您需要检查对象的实际实例


静态方法也不能实现接口;如果这个类正在实现一个
IRolesService
接口,那么我认为这个方法不应该是静态的。更好的设计是使用实例方法,这样您就可以在准备就绪时将
MockRoleService
替换为真正的服务。

您不能重写静态方法。您可能会发现一个有趣的阅读。

静态方法表示与类型本身相关的逻辑。一旦从该类型继承,就不能假定父类型的静态方法适用。您可以执行以下操作:

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

有两种方法可以使模拟对象工作:

1:将父对象的签名从RoleService更改为IRolesService(假设您尚未使用该接口)。然后实现mock-to-IRolesService,而不是roleservice

public class MockRoleService : IRolesService
{
    public new static bool IsUserInRole(string username, string rolename)
    {
        return true;
    }
}
  • 依赖注入角色对象
  • 公共类MockRoleService:RoleService {


    }

    要调用静态方法,您需要以下类型的直接引用:

    RolesService.IsUserInRole(...);
    
    在这种情况下,如果您希望能够调用“派生”类的静态方法,则删除“new”关键字将允许您:

    MockRoleService.IsUserInRole(...);
    
    并获得预期的函数调用

    我猜这不是你想要的。您的代码中可能有一些调用,比如前一个,您希望通过使用模拟工具创建MockRoleService,您将注入这种新的“类型”来代替旧的。不幸的是,这不是静态的工作方式

    模拟工具将创建模拟类型的实例,并将插入该实例以代替构造真实类型的调用。对静态方法的调用会跳过所有这些

    正如Aaronaught提到的,您可能应该将此方法设置为普通实例方法。这将允许正确注入模拟服务来代替常规RoleService,允许将方法声明移动到IRolesService接口中,并在MockRoleService实现中重写它。然后,在“获取”角色服务的代码中,只需调用实例成员而不是静态成员

    IRolesService svc = MyServiceInjector.GetService<IRolesService>();
    svc.IsUserInRole(...);
    
    IRolesService svc=MyServiceInjector.GetService();
    svc.IsUserInRole(…);
    
    执行以下操作将允许您绕过静态调用。在您想要使用代码的地方,通过依赖项注入获取IRolesService,然后当您需要MockRoleService时,可以将其传入

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

    像这样的东西怎么样:

    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;
        }
    }
    
    公共接口IRolesService
    {
    bool IsUserInRoleImpl(字符串用户名、字符串角色名);
    }
    公共抽象类RoleServiceBase,其中T:IRolesService,new()
    {
    受保护的静态T角色服务=新T();
    公共静态bool IsUserInRole(字符串用户名、字符串角色名)
    {
    返回RoleService.IsUserInRoleImpl(用户名,rolename);
    }
    }
    公共类角色服务:角色服务库,iRoleService
    {
    public bool IsUserInRoleImpl(字符串用户名、字符串角色名)
    {
    返回Roles.IsUserInRole(用户名,rolename);
    }
    }
    公共类MockRoleService:RoleServiceBase,iRoleService
    {
    public bool IsUserInRoleImpl(字符串用户名、字符串角色名)
    {
    返回true;
    }
    }
    
    我也有类似的问题。我没有使用继承或接口,只是使用了委托

        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;
    

    为什么不使用属性来访问静态值?然后它将支持继承并可重写。这似乎就是你要找的

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

    最后一个方法中对IsUserInRole的调用不明确,需要调用MockRoleService。IsUserInRole@Thomas不确定您是在我的编辑之前还是之后看到了代码,但在当前示例中,对IsUserInRole的调用调用了MockRoleService.IsUserInRole。我想他理解您不能重写静态方法。他的问题是“有什么想法吗?”来回避这个问题。不确定人们是否意识到了这一点,因为除了Aaronaught之外,所有的投票结果都不包含任何绕过这一点的想法。现在,
    IsUserInRole
    不再是一种静态方法。
    public class StaticOverride {
        public virtual string MyVal { get { return MyStaticMethod(); } }
    
        public string MyStaticMethod () {
            return "Example";
        }
    }