[英]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#中理解和实现装饰模式” 。
当您使用A
和B
功能装饰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.