克隆c#中的方法

时间:2014-08-09 01:15:11

标签: c#

假设我有一个A类:

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

和B级:

class B
{
    A m;
}

这样,如果我写B x,我可以致电x.m.b()

我需要的是在B类中动态创建方法b(),因此我可以将其用作x.b()(当然,来自调用x.m.b()和{{1的结果应该是一样的)。

我该怎么做?

5 个答案:

答案 0 :(得分:3)

您可以使用委托来完成此操作,在现代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
}

也可以用经典方法来做,只是暴露一个完全相同的b方法,在这里看不到任何特殊/困难的东西?如果您正在尝试完成其他任务,则需要澄清您的问题,例如,如果您想要自动执行此操作,则可以轻松编译时间(T4文本模板)或在运行时(生成动态代理)。

答案 1 :(得分:3)

有一个通用解决方案(您不必为所需的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();

答案 2 :(得分:1)

你要做的是在C#中实现装饰器模式。

  

GoF将Decorator模式定义为&#34;附加其他职责   动态地对象。装饰器提供了灵活的替代品   子类化以扩展功能。

我建议您仔细阅读本文"Understanding and Implementing Decorator Pattern in C#"

当您使用ConcreteA功能装饰B时,我创建了一个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时A1_with_c_method,A2_with_c_method,A3_with_c_methos,   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();
    }
}

答案 3 :(得分:0)

我同意这些评论,这看起来很奇怪,我想知道为什么你会想要这样做,但这是你的可能性。

interface IHasMethodb
{
    void b();
}

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

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

这是你想要做的吗?

答案 4 :(得分:0)

看起来你要么想要包装一个方法的概念,在你的例子中就像这样简单:

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

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

允许你:

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

如果您希望能够动态创建&#34;然后,这可能更适用,使用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();