假设我有一个A类:
class A
{
void b() {...}
}
和B级:
class B
{
A m;
}
这样,如果我写B x
,我可以致电x.m.b()
。
我需要的是在B类中动态创建方法b()
,因此我可以将其用作x.b()
(当然,来自调用x.m.b()
和{{1的结果应该是一样的)。
我该怎么做?
答案 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#"。
当您使用Concrete
和A
功能装饰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();