繁体   English   中英

克隆c#中的方法

[英]Cloning a method in c#

假设我有一个A类:

class A
{
    void b() {...}
}

和B级:

class B
{
    A m;
}

这样,如果我写B x ,我可以调用xmb()

我需要在B类内部动态创建方法b() ,因此可以将其用作xb() (当然,调用xmb()xb()应该相同)。

我该怎么做?

您可以使用代理来完成此操作,在现代C#中,这可能看起来像这样

public class A
{
    public void b() {...}
}

public class B
{
    private A m = new A();
    public Action b = ()=>m.b();
}

public void Main()
{
     new B().b(); // This now invokes your delegates that invokes the b method on it's internal m object
}

也可以只用经典方法来做,而只是公开做完全相同的事情的ab方法,在这里看不到什么特别/困难的地方吗? 如果您正在尝试完成其他任务,则需要澄清您的问题,例如,如果您想要自动执行此操作,则可以轻松编译时间(T4文本模板)或在运行时(生成动态代理)。

有一个通用的解决方案(在这里您将不必FE从每个方法创建代表A你想要的)。 不幸的是,它不会是强类型的。 如果您愿意,请参阅其他答案。

class A
{
    public int B()
    {
        return 1;
    }
}

class B : DynamicObject
{
    private readonly A m = new A();

    private static readonly Lazy<IEnumerable<MethodInfo>> AMethods =
        new Lazy<IEnumerable<MethodInfo>>(() =>
                                          {
                                              var type = typeof (A);
                                              return type.GetMethods(
                                                  BindingFlags.Instance | 
                                                  BindingFlags.Public);
                                          });

    public override bool TryInvokeMember(
                           InvokeMemberBinder binder, 
                           object[] args, 
                           out object result)
    {
        if (base.TryInvokeMember(binder, args, out result))
        {
            return true;
        }

        var methods = AMethods.Value;

        var method = methods.SingleOrDefault(mth => mth.Name == binder.Name); 
            // TODO: additional match (arguments type to handle overloads)
        if (method == null)
        {
            result = null;
            return false;
        }

        result = method.Invoke(this.m, args);

        return true;
    }

    public int OtherBMethods()
    {
        return 2;
    }
}

用法:

var b = new B();  
int result = ((dynamic)b).B();    
int other = b.OtherBMethods(); 

要么

dynamic b = new B();
int result = b.B();
int other = b.OtherBMethods();

你要做的是在C#中实现Decorator模式。

GoF将Decorator模式定义为“动态附加对象的附加职责。装饰器为子类化提供了灵活的替代,以扩展功能。

我想推荐一下这篇文章“在C#中理解和实现装饰模式”

当您使用AB功能装饰Concrete时,我创建了Decorator模式实现的简单示例。

interface IDecorator
{
    void Print();
}

class Concrete : IDecorator
{
    public void Print()
    {
        Console.WriteLine("-> Concrete");
    }
}

class A : IDecorator
{
    IDecorator decorator;
    public A(IDecorator decorator)
    {
        this.decorator = decorator;
    }
    public void Print()
    {
        decorator.Print();
        Console.WriteLine("-> A");
    }
}

class B : IDecorator
{
    IDecorator decorator;
    public B(IDecorator decorator)
    {
        this.decorator = decorator;
    }
    public void Print()
    {
        decorator.Print();
        Console.WriteLine("-> B");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("concrete object that should be decorated");
        var concrete = new Concrete();
        concrete.Print();

        Console.WriteLine("let's decorate this object with A decorator");
        var decoratedWithA = new A(concrete);
        decoratedWithA.Print();

        Console.WriteLine("let's decorate this object with B decorator");
        var decoratedWithB = new B(concrete);
        decoratedWithB.Print();

        Console.WriteLine("let's decorate concrete with A and B");
        var decoratedWithAB = new B(new A(concrete));
        decoratedWithAB.Print();
    }
}

我有一个抽象的A类和类A1:A,A2:A,A3:A。然后我还有一个名为c()的方法。 我想创建类A1_with_c_method,A2_with_c_method,A3_with_c_methos,同时不破坏A1,A2和A3。 做这个的最好方式是什么? - h8red

你可以这样做:

abstract class A
{
}

class A1 : A
{
}

class A2 : A
{
}

class A3 : A
{
}

#region Not a good idea, because too many classes

class A1_with_c : A1
{
    public void c() { }
}

class A2_with_c : A2
{
    public void c() { }
}

class A3_with_c : A3
{
    public void c() { }
}

#endregion


// Decorate A with the c() method
class BaseDecorator
{
    public A Instance { get; private set; }
    public BaseDecorator(A instance)
    {
        Instance = instance;
    }

    public virtual void c()
    {
        // do something with instance
    }
}

class Decorator : BaseDecorator
{
    BaseDecorator decorator;
    public Decorator(BaseDecorator decorator)
        : base(decorator.Instance)
    {
        this.decorator = decorator;
    }
    public override void c()
    {
        Console.WriteLine("Ok");
    }
}

class Program
{
    static void Main(string[] args)
    {
        // not good
        new A1_with_c().c();
        new A2_with_c().c();
        new A3_with_c().c();

        // better
        var a_with_c = new BaseDecorator(new A1());
        a_with_c.c();

        // Let's decorate with something interesting
        new Decorator(a_with_c).c();
    }
}

我同意这样的说法,即这确实看起来很奇怪,我想知道为什么您会想要这样做,但是这对您来说是一种可能性。

interface IHasMethodb
{
    void b();
}

class A : IHasMethodb
{
    public void b() { ... }
}

class B : IHasMethodb
{
    A m;
    public void b() { return m.b(); }
}

这是你想要做的吗?

似乎您要么想要包装一个方法的概念,在您的示例中它就很简单:

class A {
   public void b() { ... }
}

class B {
   A m;
   public void b() { m.b(); }
}

允许您:

B x = new B();
x.b();

如果您希望能够“动态创建”该方法,那么这可能更适用,使用Action<T>允许您使用A实例执行任何操作,而不实际暴露它:

class A {
   public void b() {...}
}

class B {
   A m;
   public Action<A> doSomethingWithA;

   public void b() {
      if (doSomethingWithA != null)
         doSomethingWithA(m);
   }
}

那么你也能:

B x = new B();
x.doSomethingWithA = a => a.b();
x.b();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM