我通过继承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;
}
}
答案 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;
}
}
公共类MockRoleService:RolesService {
public MockRoleService ()
{
Roles = OverridenRolesObjectThatAlwaysReturnsTrue;
}
}
答案 9 :(得分:0)
为什么不使用属性来访问静态值?然后它将支持继承并且可以覆盖。这似乎是你正在寻找的东西。
public class StaticOverride {
public virtual string MyVal { get { return MyStaticMethod(); } }
public string MyStaticMethod () {
return "Example";
}
}