C# 覆盖静态方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2074454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Override a static method
提问by Gabe
I am extending a new class by inheriting from RolesService. In RolesService I have a static methog that I would like to override in my newly derived class. When I make the call from my derived object it does not use the overridden static method it actually calls the base class method. Any ideas?
我通过从 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;
}
}
采纳答案by mhinton
Doing the following the will allow you to work around the static call. Where you want to use the code take an IRolesService via dependency injection then when you need MockRolesService you can pass that in.
执行以下操作将允许您解决静态调用。你想使用代码的地方通过依赖注入获取 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;
}
}
回答by Thomas Levesque
You can't override a static method. A static method can't be virtual, since it's not related to an instance of the class.
您不能覆盖静态方法。静态方法不能是虚拟的,因为它与类的实例无关。
The "overriden" method in the derived class is actually a new method, unrelated to the one defined in the base class (hence the new
keyword).
派生类中的“覆盖”方法实际上是一种新方法,与基类中定义的方法无关(因此是new
关键字)。
回答by Aaronaught
You cannot override a static method.
您不能覆盖静态方法。
If you think about it, it doesn't really make sense; in order to have virtual dispatch you need an actual instance of an object to check against.
如果你仔细想想,这真的没有意义;为了进行虚拟调度,您需要一个对象的实际实例进行检查。
A static method also can't implement an interface; if this class is implementing an IRolesService
interface then I would contend that the method should not be static at all. It's better design to have an instance method, so you can swap out your MockRoleService
with a real service when you're ready.
静态方法也不能实现接口;如果这个类正在实现一个IRolesService
接口,那么我认为该方法根本不应该是静态的。拥有一个实例方法是更好的设计,所以MockRoleService
当你准备好时,你可以用一个真正的服务来替换你的。
回答by keyboardP
回答by G-Wiz
A static method represents logic pertinent to the type itself. Once you inherit from that type, the static methods of the parent type cannot be assumed to apply. What you can do is the following:
静态方法表示与类型本身相关的逻辑。一旦从该类型继承,就不能假定应用父类型的静态方法。您可以执行以下操作:
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;
}
}
回答by Jason Hernandez
There are two ways you might make your mock object work:
有两种方法可以让你的模拟对象工作:
1: Change the signature of your parent object from RolesService to IRolesService (assuming you aren't using the Interface already) . Then implement the mock to IRolesService instead of RolesService.
1:将您的父对象的签名从 RolesService 更改为 IRolesService(假设您尚未使用该接口)。然后将模拟实现为 IRolesService 而不是 RolesService。
public class MockRoleService : IRolesService
{
public new static bool IsUserInRole(string username, string rolename)
{
return true;
}
}
- Dependency inject the Roles object.
- 依赖注入 Roles 对象。
public class MockRoleService : RolesService {
公共类 MockRoleService : RolesService {
public MockRoleService ()
{
Roles = OverridenRolesObjectThatAlwaysReturnsTrue;
}
}
}
回答by Jeff Wight
In order to call a static method, you'll need a direct reference of the type:
为了调用静态方法,您需要一个类型的直接引用:
RolesService.IsUserInRole(...);
In which case, if you want to be able and call the "derived" class's static method, dropping the "new" keyword will allow you to:
在这种情况下,如果您希望能够调用“派生”类的静态方法,删除“new”关键字将允许您:
MockRoleService.IsUserInRole(...);
and get the expected function call.
并获得预期的函数调用。
My guess is that this isn't what you're looking for. You likely have some call somewhere in your code like the former, and you're hoping that by using a Mocking tool to create a MockRoleService, you'd be injecting this new "type" in place of the old one. Unfortunately, that's not how it works with statics.
我的猜测是这不是你要找的。您可能在代码中的某处有一些调用,就像前者一样,并且您希望通过使用 Mocking 工具创建 MockRoleService,您将注入这个新的“类型”来代替旧的“类型”。不幸的是,这不是静态的工作方式。
A mocking tool will create an instance of the mocked out type and will inject that in place of a call to construct the real type. A call to a static method skips all of that.
模拟工具将创建模拟出的类型的实例,并将注入该实例来代替构造真实类型的调用。对静态方法的调用会跳过所有这些。
As Aaronaught mentioned, you should probably make this method a normal instance method. This would allow your mock service to be properly injected in place of your regular RolesService, allow you to move the method declaration into your IRolesService interface, and override it in your MockRoleService implementation. Then, in the code where you "get" a RolesService, you just call the instance member instead of the static.
正如 Aaronaught 所提到的,您可能应该将此方法设为普通的实例方法。这将允许您的模拟服务被正确注入以代替您的常规 RolesService,允许您将方法声明移动到您的 IRolesService 接口中,并在您的 MockRoleService 实现中覆盖它。然后,在“获取” RolesService 的代码中,您只需调用实例成员而不是静态成员。
IRolesService svc = MyServiceInjector.GetService<IRolesService>();
svc.IsUserInRole(...);
回答by fre0n
What about something like this:
这样的事情怎么样:
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;
}
}
回答by Joe B
I had a similar problem. I didn't use inheritance or an interface, but simply used a delegate.
我有一个类似的问题。我没有使用继承或接口,只是使用了一个委托。
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);
}
}
If you want to change the method to "newMethod" for testing purposes, just call
如果您想将方法更改为“newMethod”以进行测试,只需调用
RolesService.isUserInRoleFunction = newMethod;
回答by Ash Blue
Why not use a property to access the static value? Then it would support inheritance and be overridable. Which seems to be what you're looking for.
为什么不使用属性来访问静态值?然后它将支持继承并且是可覆盖的。这似乎是你要找的。
public class StaticOverride {
public virtual string MyVal { get { return MyStaticMethod(); } }
public string MyStaticMethod () {
return "Example";
}
}