将覆盖附加到C#类
我有一个函数类:将覆盖附加到C#类,c#,overriding,aop,C#,Overriding,Aop,我有一个函数类: class MyClass { public List<Attachment> Attachments; public void A() { // Do something } public void B() { // Do something } } class AttachmentA : Attachment { public void A() {
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
}
}
编辑:我想在这里实现的是具有属性(=附件)的单元。当装置获得RandomSpeed
附件时,RandomSpeed
将覆盖装置的GetSpeed
并返回随机值。当它获得规避附件时,它将覆盖unitsReduceHP
函数,有时基于随机值不会调用基函数
编辑:真正解决这一混乱局面的方法是以某种方式使用反射来更改虚拟方法表,我将对一个单独的问题进行跟进。我把这个问题保留在这里,以防有人找到更好的方法。如果您不想在MyClass上引入依赖项,如继承或接口,那么: 您可以通过委派来实现这一点 长话短说,在运行时,若不借助一些模糊的反射魔法,就无法重写函数,但可以声明委托而不是函数。当您在构造函数中构造类时,请使用私有方法填充委托,只要没有AttachmentA类进入,就可以使用私有方法。并使用这些委托而不是方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
static class Program
{
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
}
}
class MyClass
{
public List<Attachment> Attachments;
public MyClass()
{
A = _A;
B = _B;
Attachments = new List<Attachment>();
}
public void Attach(Attachment attachment)
{
Attachments.Add(attachment);
// this is your magic
if (attachment.GetType() == typeof(AttachmentA)) {
A = ((AttachmentA)attachment).A;
}
else if (attachment.GetType() == typeof(AttachmentB))
{
B = ((AttachmentB)attachment).B;
}
}
public delegate void delegateA();
public delegate void delegateB();
public delegateA A;
public delegateB B;
public void _A()
{
Console.WriteLine("MyClass.A");
}
public void _B()
{
Console.WriteLine("MyClass.B");
}
}
class Attachment {
}
class AttachmentA : Attachment
{
public void A()
{
Console.WriteLine("AttachmentA.A");
}
}
class AttachmentB : Attachment
{
public void B()
{
Console.WriteLine("AttachmentB.B");
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
利用制度全球化;
使用System.Runtime.InteropServices;
命名空间控制台应用程序1
{
静态类程序
{
静态void Main(字符串[]参数)
{
MyClass aaa=新的MyClass();
aaa.A();//应打印MyClass.A
aaa.B();//应打印MyClass.B
aaa.附件(新附件a());
aaa.Attach(新的AttachmentB());
aaa.A();//应打印AttachmentA.A MyClass.A
aaa.B();//应打印附件B.B
}
}
类MyClass
{
公开名单附件;
公共MyClass()
{
A=_A;
B=_B;
附件=新列表();
}
公共无效附件(附件)
{
附件。添加(附件);
//这是你的魔法
if(attachment.GetType()==typeof(AttachmentA)){
A=((附件)附件)。A;
}
else if(attachment.GetType()==typeof(AttachmentB))
{
B=((附件B)附件).B;
}
}
public delegate void delegateA();
public delegate void delegateB();
公共代表A;
公共代表B;
公共空间(A)
{
Console.WriteLine(“MyClass.A”);
}
公共空间(B)
{
Console.WriteLine(“MyClass.B”);
}
}
类附件{
}
类别附件A:附件
{
公共图书馆A()
{
Console.WriteLine(“附件A”);
}
}
类附件B:附件
{
公共空间B()
{
Console.WriteLine(“附件B.B”);
}
}
}
如果您需要始终在MyClass而不是Attachment类中开始执行,您可以像下面这样包装委托:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
static class Program
{
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
}
}
class MyClass
{
public List<Attachment> Attachments;
public MyClass()
{
Attachments = new List<Attachment>();
}
public void Attach(Attachment attachment)
{
Attachments.Add(attachment);
if (attachment.GetType() == typeof(AttachmentA)) {
_A = ((AttachmentA)attachment).A;
}
else if (attachment.GetType() == typeof(AttachmentB))
{
_B = ((AttachmentB)attachment).B;
}
}
public delegate void delegateA();
public delegate void delegateB();
public delegateA _A;
public delegateB _B;
public void A()
{
if (_A != null)
{
_A();
}
else
{
Console.WriteLine("MyClass.A");
}
}
public void B()
{
if (_B != null)
{
_B();
}
else
{
Console.WriteLine("MyClass.B");
}
}
}
class Attachment {
}
class AttachmentA : Attachment
{
public void A()
{
Console.WriteLine("AttachmentA.A");
}
}
class AttachmentB : Attachment
{
public void B()
{
Console.WriteLine("AttachmentB.B");
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
利用制度全球化;
使用System.Runtime.InteropServices;
命名空间控制台应用程序1
{
静态类程序
{
静态void Main(字符串[]参数)
{
MyClass aaa=新的MyClass();
aaa.A();//应打印MyClass.A
aaa.B();//应打印MyClass.B
aaa.附件(新附件a());
aaa.Attach(新的AttachmentB());
aaa.A();//应打印AttachmentA.A MyClass.A
aaa.B();//应打印附件B.B
}
}
类MyClass
{
公开名单附件;
公共MyClass()
{
附件=新列表();
}
公共无效附件(附件)
{
附件。添加(附件);
if(attachment.GetType()==typeof(AttachmentA)){
_A=((附件)附件)。A;
}
else if(attachment.GetType()==typeof(AttachmentB))
{
_B=((附件B)附件).B;
}
}
public delegate void delegateA();
public delegate void delegateB();
公共授权机构A(A);
公共授权机构;
公共图书馆A()
{
如果(_A!=null)
{
_A();
}
其他的
{
Console.WriteLine(“MyClass.A”);
}
}
公共空间B()
{
如果(_B!=null)
{
_B();
}
其他的
{
Console.WriteLine(“MyClass.B”);
}
}
}
类附件{
}
类别附件A:附件
{
公共图书馆A()
{
Console.WriteLine(“附件A”);
}
}
类附件B:附件
{
公共空间B()
{
Console.WriteLine(“附件B.B”);
}
}
}
如果A和B在实际场景中具有相同的参数和返回类型,则可以将其缩短为一种委托类型。我不确定是否可以动态重写类的功能,但可以通过使用不同的接口实现类似的功能。根据您希望在其中使用的上下文,它可能只需要少量的重新设计 这样做的标准方式是:
using System;
class MyClass
{
public virtual void A()
{
Console.WriteLine("MyClass.A");
}
public virtual void B()
{
Console.WriteLine("MyClass.B");
}
}
class ClassA : MyClass
{
public override void A()
{
Console.WriteLine("AttachmentA.A");
base.A();
}
}
class ClassB : MyClass
{
public override void B()
{
Console.WriteLine("AttachmentB.B");
}
}
public class Program
{
public static void Main(string[] Args)
{
MyClass aaa = new ClassA();
MyClass bbb = new ClassB();
aaa.A(); // prints MyClass.A
aaa.B(); // prints MyClass.B
(aaa as ClassA).A(); // prints AttachmentA.A
(aaa as ClassA).B(); // prints MyClass.B
bbb.A(); // prints MyClass.A
bbb.B(); // prints MyClass.B
(bbb as ClassB).A(); // prints AttachmentB.A + MyClass.A
(bbb as ClassB).B(); // prints AttachmentB.B
}
}
下面是另一个例子,类似于blowdart的建议:
interface ICallMe
{
bool A();
bool B();
}
class MyClass
{
public ICallMe Attachment { get; set; }
public void A()
{
bool BaseFunction = true;
if (Attachment != null)
BaseFunction = Attachment.A();
if (BaseFunction)
Console.WriteLine("MyClass.A");
}
public void B()
{
bool BaseFunction = true;
if (Attachment != null)
BaseFunction = Attachment.B();
if (BaseFunction)
Console.WriteLine("MyClass.B");
}
}
class ClassA : ICallMe
{
public bool A()
{
Console.WriteLine("AttachmentA.A");
return true;
}
public bool B()
{
Console.WriteLine("AttachmentA.B");
return false;
}
}
static class Program
{
static void Main(string[] args)
{
MyClass aaa = new MyClass();
aaa.A(); // prints MyClass.A
aaa.B(); // prints MyClass.B
aaa.Attachment = new ClassA();
aaa.A(); // should print AttachmentA.A <newline> MyClass.A
aaa.B(); // should print AttachmentB.B
}
}
interface-ICallMe
{
布尔A();
bool B();
}
类MyClass
{
公共ICallMe附件{get;set;}
公共图书馆A()
{
bool BaseFunction=true;
如果(附件!=null)
BaseFunction=附件A(
interface ICallMe
{
bool A();
bool B();
}
class MyClass
{
public ICallMe Attachment { get; set; }
public void A()
{
bool BaseFunction = true;
if (Attachment != null)
BaseFunction = Attachment.A();
if (BaseFunction)
Console.WriteLine("MyClass.A");
}
public void B()
{
bool BaseFunction = true;
if (Attachment != null)
BaseFunction = Attachment.B();
if (BaseFunction)
Console.WriteLine("MyClass.B");
}
}
class ClassA : ICallMe
{
public bool A()
{
Console.WriteLine("AttachmentA.A");
return true;
}
public bool B()
{
Console.WriteLine("AttachmentA.B");
return false;
}
}
static class Program
{
static void Main(string[] args)
{
MyClass aaa = new MyClass();
aaa.A(); // prints MyClass.A
aaa.B(); // prints MyClass.B
aaa.Attachment = new ClassA();
aaa.A(); // should print AttachmentA.A <newline> MyClass.A
aaa.B(); // should print AttachmentB.B
}
}