如果不存在,生成方法

3

背景

我有一个C#类PyroProxy,其中有一个call(string method, params object[] arguments)方法。

public class PyroProxy : IDisposable {

    public object call(string method, params object[] arguments)
}

这是远程对象代理类。

动机

在代码中一直使用call方法看起来不太好看。

问题

假设PyroProxy类没有test_method()方法。我该如何使下面的代码正常工作?

PyroProxy p = new PyroProxy();
p.test_method();

test_method的代码如下:

public object test_method(params object[] arguments) {
    return call("test_method", arguments); // you get the point
}

这可能是一个我没有找到的重复问题,也许可以在编译时或运行时实现。 我该怎么做才能更接近这个目标?欢迎提供提示。有关如何注入方法的答案,请参见。我找到了ExpandoObject ,但它没有告诉我如何创建未知方法。


你给出的链接没有描述你需要做什么吗?dictionary.Add("Shout", new Action(() => { Console.WriteLine("Hellooo!!!"); })); person.Shout(); - private_meta
你考虑过使用DynamicProxy吗?像Dynamic这样的东西的问题在于,为了获得魔法行为,你实际上必须调用它们,同时它们本身也是动态的。如果你声明想要重写的所有成员都是虚拟的,那么可以创建一个代理类,它只需调用调用方法并返回结果即可。尝试使用Castle DynamicProxy,因为它在这方面相当不错。它稍微有点慢,但由于你正在代理远程调用,所以没有任何影响。 - Michael B
@MichaelB,我不明白你在写什么。你能加上一些链接并把你的评论变成答案吗?虽然我不是新手,但我对C#还不熟悉。我从哪里获取“DynamicProxy”? - User
我推荐使用类似 http://www.castleproject.org/projects/dynamicproxy/ 的工具,其思想是把你想要代理的类中所有成员声明为虚拟的。构建一个拦截器,它只需要使用代理调用类的 call 方法并传递方法名。使用 Castle 的工具生成继承类,从而使用拦截器。代理覆盖了所有成员,并添加了对拦截器的调用。与使用 dynamic 相比,优点在于你可以使用此代理类而无需将其声明为 dynamic,因此代码类型更安全。 - Michael B
谢谢,我会自己搜索一下。看起来很有前途。如果你没有的话,我会发布一个答案。 - User
显示剩余3条评论
2个回答

6
你需要从 DynamicObject 派生,并重写 TryInvokeMember 方法。
public class PyroProxy : DynamicObject
{
    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        Console.WriteLine(binder.Name + " was invoked");
        result = call(binder.Name, args);
        return true;
    }
}

dynamic proxy = new PyroProxy();
proxy.SomeMethod(); //prints "SomeMethod was invoked"

我选择了这个解决方案,尽管它还没有被实现,因为它捕捉到了代理所涉及的语言的动态特性。如果需要的话,它也可以将getWidth()转换为get_width(),以保持语言风格的连贯性。这里是我们本来想用它来完成的项目。 - User
您的建议已经被采纳并应用到了Pyrolite的代码中。非常感谢! - User

3

为什么不使用扩展方法

public static class ExtensionMethods
{
    public static object test_method(this PyroProxy proxy, params object[] arguments)
    {
        return proxy.call("test_method", arguments); // you get the point
    }
}

2
我更喜欢这种方法,而不是“自动生成代理”,这可以让你跟踪应用程序实际使用的方法,并防止拼写错误破坏你的一天。 - C.Evenhuis
我可以像这样做吗? public static class ExtensionMethods:DynamicObject?我只是好奇。 - User
不,扩展方法只是在this关键字之后假装该方法属于类。包含它的类必须是静态的,因此我认为在您的情况下无法使用。 - Patrick Hofman
1
@C.Evenhuis 同意。除非我在问题中漏看了什么,否则这个答案对我来说比使用“dynamic”的答案要好得多。代码中没有错别字错误,唯一一个方法名称硬编码的地方是在一个单独的静态类中。 - ken2k
@用户:对于您的问题和提出的解决方案有什么想法吗? - Patrick Hofman
是的,两者都是同样有效的。我会评估它们,并在我实现了某些东西后回来。 - User

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接