将重写附加到 C# 类
我有一个带有函数的类:
class MyClass
{
public List<Attachment> Attachments;
public void A()
{
// Do something
}
public void B()
{
// Do something
}
}
class AttachmentA : Attachment
{
public void A()
{
// Do something else
RealA();
}
}
class AttachmentB : Attachment
{
public void B()
{
// Do something else
// RealB();
// No need to call base function here
}
}
当我将 AttachmentA
附加到 MyClass
时,我需要在代码中包含 MyClass
中也存在的所有函数AttachmentA
将被 AttachmentA
中的函数覆盖,并且还可以访问 MyClass
中的原始函数。
例如,我创建 MyClass
,然后将 AttachmentA
实例附加到它。调用 MyClass.A()
实际上会调用 AttachmentA.A()
,而 AttachmentA.RealA()
将调用被重写的基函数.
我知道这可以通过使用事件处理程序列表来处理覆盖之类的方式来完成,但是有没有一种简单的方法来实现这一点?
编辑:我对使用反射的长代码没有问题,只要它出现一次,甚至不必在任何函数中提及 - 也许仅在附加附件时。
编辑:你想要一个例子:
class MyClass
{
public List<Attachment> Attachments;
public MyClass()
{
Attachments = new List<Attachment>();
}
public void Attach(Attachment attachment)
{
Attachments.Add(attachment);
// Do some magic here
}
public void A()
{
Console.WriteLine("MyClass.A");
}
public void B()
{
Console.WriteLine("MyClass.B");
}
}
class AttachmentA : Attachment
{
public void A()
{
Console.WriteLine("AttachmentA.A");
RealA();
}
}
class AttachmentB : Attachment
{
public void B()
{
Console.WriteLine("AttachmentB.B");
}
}
public class Program
{
public static void Main(string[] Args)
{
MyClass aaa = new MyClass();
aaa.A(); // should print MyClass.A
aaa.B(); // should print MyClass.B
aaa.Attach(new AttachmentA());
aaa.Attach(new AttachmentB());
aaa.A(); // should print AttachmentA.A <newline> MyClass.A
aaa.B(); // should print AttachmentB.B
}
}
编辑:我想在这里实现的就像带有属性的单元(=附件)。当设备获得RandomSpeed
附件时,RandomSpeed
将覆盖设备的GetSpeed
并返回随机值。当它获得逃避附件时,它将覆盖该单位的ReduceHP函数,有时基于随机值不会调用基本函数。
编辑:真正解决这个混乱的方法是以某种方式使用反射来更改虚拟方法表,我将在一个单独的问题上进行后续处理。我将这个问题保留在这里,以防有人找到更好的方法来做到这一点。
I have a class with functions:
class MyClass
{
public List<Attachment> Attachments;
public void A()
{
// Do something
}
public void B()
{
// Do something
}
}
class AttachmentA : Attachment
{
public void A()
{
// Do something else
RealA();
}
}
class AttachmentB : Attachment
{
public void B()
{
// Do something else
// RealB();
// No need to call base function here
}
}
I need in my code when I attach AttachmentA
to MyClass
that all the functions in MyClass
that are also present in AttachmentA
to be overridden by the functions in AttachmentA
and also give access to the original functions in MyClass
.
For example, I create MyClass
and then attach AttachmentA
instance to it. calling MyClass.A()
will actually call AttachmentA.A()
and the AttachmentA.RealA()
will call the base function that was overridden.
I know this can be somehow done with something like using event handlers lists to handle overrides but is there an easy way to implement this?
Edit: I have no problem with long code that uses reflection as long as its present once and doesn't have to be even mentioned in any of the functions - maybe only when attaching attachement.
Edit: you wanted an example:
class MyClass
{
public List<Attachment> Attachments;
public MyClass()
{
Attachments = new List<Attachment>();
}
public void Attach(Attachment attachment)
{
Attachments.Add(attachment);
// Do some magic here
}
public void A()
{
Console.WriteLine("MyClass.A");
}
public void B()
{
Console.WriteLine("MyClass.B");
}
}
class AttachmentA : Attachment
{
public void A()
{
Console.WriteLine("AttachmentA.A");
RealA();
}
}
class AttachmentB : Attachment
{
public void B()
{
Console.WriteLine("AttachmentB.B");
}
}
public class Program
{
public static void Main(string[] Args)
{
MyClass aaa = new MyClass();
aaa.A(); // should print MyClass.A
aaa.B(); // should print MyClass.B
aaa.Attach(new AttachmentA());
aaa.Attach(new AttachmentB());
aaa.A(); // should print AttachmentA.A <newline> MyClass.A
aaa.B(); // should print AttachmentB.B
}
}
Edit: What I want to achieve here is like unit with attributes( = attachments). When the unit get an attachment of RandomSpeed
, RandomSpeed
will override the unit's GetSpeed
and return random value. when it will get an attachment of evasion, it will override that units ReduceHP
function and sometimes based on random value will not call the base function.
Edit: What will really solve this mess is to somehow use reflection to change virtual method tables, I'm gonna make a followup on a separate question. I keep this question here incase someone find a better way to do this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
正如评论中提到的,装饰器模式就是您正在寻找的。
http://en.wikipedia.org/wiki/Decorator_pattern
As mentioned in comments, Decorator Pattern is what you are looking for.
http://en.wikipedia.org/wiki/Decorator_pattern
为什么不采取另一种方法呢?让附件根据想要覆盖的内容实现接口,例如 ISpeedAttachment。然后,您可以在基本速度函数中循环遍历实现 ISpeedAttachment 的附件,并调用它们。
如果接口尚未生效,则让它们返回 null,然后您可以检查它们是否都返回 null 并根据需要调用基类,或者传入一个 ref 参数,您可以根据需要调整该参数。
Why not take another approach? Have attachments implement interfaces based on what they want to override, for example ISpeedAttachment. Then you could, in the base speed function loop through attachments which implement ISpeedAttachment, calling them.
Have the interfaces return null if they haven't taken effect and you could then check they've all returned null and call the base class as appropriate, or pass in a ref parameter which you could adjust as necessary.
您应该研究一下行为模式。对于您的特定问题,我建议使用 责任链 或 策略模式。
You should look into the behavioral patterns. For your particular problem I would recommend either the chain of responsibility or the strategy pattern.
如果您不想引入依赖项,例如在 MyClass 上实现的继承或接口,那么:
您可以通过委托来实现这一点。
长话短说,如果不诉诸一些晦涩的反射魔法,您就无法在运行时重写函数,但是您可以声明委托而不是函数。当您在构造函数中构造类时,用私有方法填充委托,只要没有 AttachmentA 类进入,就会使用这些私有方法。并使用这些委托而不是方法。
如果您需要始终在 MyClass 而不是 Attachment 类中启动执行,您可以像下面这样包装委托:
如果 A 和 B 在实际场景中具有相同的参数和返回类型,则可以将其缩短为一种委托类型。
If you don't want to introduce dependencies, like inheritance or interfaces to implement on MyClass then:
You can achieve this through delegates.
Long story short, you cannot override function in runtime without resorting to some obscure reflection magic, but you can declare delegates instead of functions. When you construct your class in the constructor fill the delegates with private methods which will be used for as long as no AttachmentA class comes in. And use those delegates instead of the methods.
If you need the execution to start always in MyClass instead of the Attachment class you can wrap the delegates like here:
You can shorten this to one delegate type if A and B have the same parameters and return type in your real scenario.
我不确定是否可以动态覆盖类的功能,但您可以通过使用不同的接口来实现类似的功能。根据您想要使用它的上下文,它可能只需要进行少量的重新设计。
标准的做法是这样的:
这是另一个例子,类似于blowdart的建议:
这只允许添加一个附件。如果您想分别覆盖多个函数的行为,您可以使用某种集合来保存附件。在基类中,您需要循环遍历它们并找到您想要执行的类。
I'm not sure if dynamically overriding a class's functionality is possible, but you can achieve something similar by using different interfaces. Depending on the context you want to use this in, it may require only small redesign.
The standard way of doing it would be this:
Here's another example, similar to what blowdart suggested:
This only allows for a single attachment to be added. If you wanted to override the behavior of several functions separately, you could use a Collection of some sort to hold the attachments. Within the base class you'd need to loop through them and find the one you want to execute.