gpt4 book ai didi

c# - 如何代理对对象实例的调用

转载 作者:行者123 更新时间:2023-11-30 15:10:47 25 4
gpt4 key购买 nike

编辑:更改了问题标题“Does C# allow method overloading, PHP style (__call)?” - 发现它与实际问题没有太大关系。还编辑了问题文本。

我想要完成的是代理对对象方法实例的调用,因此我可以记录对其任何方法的调用。

现在,我有类似这样的代码:

class ProxyClass {
static logger;
public AnotherClass inner { get; private set; }
public ProxyClass() { inner = new AnotherClass(); }
}

class AnotherClass {
public void A() {}
public void B() {}
public void C() {}
// ...
}

// meanwhile, in happyCodeLandia...
ProxyClass pc = new ProxyClass();
pc.inner.A(); // need to write log message like "method A called"
pc.inner.B(); // need to write log message like "method B called"
// ...

那么,我怎样才能以可扩展的方式代理对对象实例的调用呢?方法重载将是最明显的解决方案(如果以 PHP 方式支持)。通过可扩展,意味着我不必在 AnotherClass 更改时修改 ProxyClass。

在我的例子中,AnotherClass 可以有任意数量的方法,因此不适合重载或包装所有方法来添加日志记录。

我知道这可能不是解决此类问题的最佳方法,所以如果有人知道使用哪种方法,请提出。

谢谢!

最佳答案

呼应另外两个; DI 是必经之路。 Dynamic Proxy在这方面非常称职。

这里是一些示例代码,完成了所有需要的实现。通常,针对接口(interface)进行编码是一种很好的做法。

我可以推荐阅读一些关于 AOP 的内容,这是我的主题: Help and Information about Aspect Oriented Programming

(编辑:因为你很好并且给了我一些分数,这里是另一个很酷的 DP 教程链接,它做得非常好:http://kozmic.pl/archive/2009/04/27/castle-dynamic-proxy-tutorial.aspx ;))

示例代码如下:

using System;
using System.Collections.Generic;
using Castle.Core;
using Castle.Core.Interceptor;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using NUnit.Framework;

[TestFixture]
public class LoggingMethodInvocationsTests
{
[Test]
public void CanLogInvocations()
{
var container = new WindsorContainer();
container.Register(Component.For<LoggingInterceptor>().LifeStyle.Singleton);
// log all calls to the interface
container.Register(Component.For<IA>().ImplementedBy<A>().Interceptors(typeof (LoggingInterceptor)));

var a = container.Resolve<IA>();
a.AMethod(3.1415926535); // to interface
Console.WriteLine("End of test");
}
}

public class LoggingInterceptor : IInterceptor, IOnBehalfAware
{
private string _entityName;

public void Intercept(IInvocation invocation)
{
var largs = new List<string>(invocation.Arguments.Length);

for (int i = 0; i < invocation.Arguments.Length; i++)
largs.Add(invocation.Arguments[i].ToString());

var a = largs.Count == 0 ? "[no arguments]" : string.Join(", ", largs.ToArray());
var method = invocation.Method == null ? "[on interface target]" : invocation.Method.Name;

Console.WriteLine(string.Format("{0}.{1} called with arguments {2}", _entityName, method, a));

invocation.Proceed();

Console.WriteLine(string.Format("After invocation. Return value {0}", invocation.ReturnValue));
}

public void SetInterceptedComponentModel(ComponentModel target)
{
if (target != null)
_entityName = target.Implementation.FullName;
}
}

public class A : IA
{
public double AMethod(double a)
{
Console.WriteLine("A method impl");
return a*2;
}

public void SecondMethod(double a)
{
Console.WriteLine(string.Format("Impl: SecondMethod called with {0}", a));
}
}

public interface IA
{
double AMethod(double a);
}

控制台输出

Examples.A.AMethod called with arguments 3,1415926535A method implAfter invocation. Return value 6,283185307End of test

关于c# - 如何代理对对象实例的调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2980727/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com