覆盖静态方法

时间:2010-01-15 20:09:15

标签: c# asp.net asp.net-mvc

我通过继承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;
    }
}

10 个答案:

答案 0 :(得分:40)

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

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

答案 1 :(得分:19)

执行以下操作将允许您解决静态调用。你想要使用代码的地方通过依赖注入获取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;
    }
}

答案 2 :(得分:18)

您无法覆盖静态方法。

如果你考虑一下,它就没有意义;为了进行虚拟调度,您需要一个要检查的对象的实际实例。

静态方法也无法实现接口;如果这个类正在实现一个IRolesService接口,那么我认为该方法根本不应该是静态的。拥有实例方法的设计更好,因此您可以在准备好时将MockRoleService换成真实服务。

答案 3 :(得分:12)

您无法覆盖静态方法。您可能会发现this是一个有趣的读物。

答案 4 :(得分:3)

为了调用静态方法,您需要直接引用类型:

RolesService.IsUserInRole(...);

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

MockRoleService.IsUserInRole(...);

并获得预期的函数调用。

我的猜测是,这不是你想要的。您可能在代码中的某个地方有一些调用,就像前者一样,并且您希望通过使用Mocking工具创建MockRoleService,您将注入这个新的“类型”来代替旧的“类型”。不幸的是,这不适用于静力学。

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

正如Aaronaught所说,你应该把这个方法变成普通的实例方法。这将允许您的模拟服务被正确注入以代替常规的RolesService,允许您将方法声明移动到IRolesService接口中,并在MockRoleService实现中覆盖它。然后,在您“获取”RolesService的代码中,您只需调用实例成员而不是静态。

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

答案 5 :(得分:3)

这样的事情:

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

答案 6 :(得分: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;

答案 7 :(得分: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;
    }
}

答案 8 :(得分:0)

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

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

public class MockRoleService : IRolesService
{
    public new static bool IsUserInRole(string username, string rolename)
    {
        return true;
    }
}
  1. 依赖项注入Roles对象。
  2. 公共类MockRoleService:RolesService {

    public MockRoleService ()
    {
         Roles = OverridenRolesObjectThatAlwaysReturnsTrue;
    }
    

    }

答案 9 :(得分:0)

为什么不使用属性来访问静态值?然后它将支持继承并且可以覆盖。这似乎是你正在寻找的东西。

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

    public string MyStaticMethod () {
        return "Example";
    }
}
相关问题