【问题标题】:C# dynamic executing function by its name?C# 动态执行函数的名称?
【发布时间】:2012-11-16 09:21:10
【问题描述】:

我有一个动态变量

dynamic d = GetSomeObject();

将来某个时候,用户向我发送一个要执行的函数(其name),例如"UsersGetAll"

所以我需要做类似的事情:d.UsersGetAll()

我可以通过反思来做到这一点。但我想使用 DLR。

这样做的唯一解决方案是让MyObject 继承自DynamicObject,然后实现TryInvokeMember

如果我无法控制班级怎么办?

【问题讨论】:

  • 想要使用 DLR 的原因是什么? AFAIK dynamic 语言功能旨在简化对未知对象的已知方法调用。也许在运行时生成代码供 Roslyn 编译?

标签: c# .net dynamic .net-4.0


【解决方案1】:

正如 Jon 所说,以下内容仅适用于您怀疑类型 在运行时通过 DLR 提供方法的情况;在大多数简单的情况下,反射会更容易。

dynamic 适用于您知道方法名称但不知道目标的情况。如果您不知道方法名称,那就更麻烦了。棘手的一点可能是确保您保留调用站点以便可以重复使用它(这就是 DLR 保持性能的方式)。一种厚颜无耻的方法是使用静态实用程序类来跟踪调用的方法。这是一个示例 - 请注意,如果您需要处理参数,它会变得很多混乱:

using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections;
using System.Runtime.CompilerServices;
public class Foo
{
    public object Bar() { return "I was here"; }
}
static class Program
{
    static void Main()
    {
        object obj = new Foo();
        object result = DynamicCallWrapper.Invoke(obj, "Bar");
        Console.WriteLine(result);
    }
}

static class DynamicCallWrapper
{
    // Hashtable has nice threading semantics
    private static readonly Hashtable cache = new Hashtable();
    public static object Invoke(object target, string methodName)
    {
        object found = cache[methodName];
        if (found == null)
        {
            lock (cache)
            {
                found = cache[methodName];
                if(found == null)
                {
                    cache[methodName] = found = CreateCallSite(methodName);
                }
            }
        }
        var callsite = (CallSite<Func<CallSite, object,object>>)found;
        return callsite.Target(callsite, target);
    }
    static object CreateCallSite(string methodName)
    {
        return CallSite<Func<CallSite, object, object>>.Create(
            Binder.InvokeMember(
            CSharpBinderFlags.None, methodName, null, typeof(object),
            new CSharpArgumentInfo[] {
                CSharpArgumentInfo.Create(
                     CSharpArgumentInfoFlags.None, null) }));

    }
}

【讨论】:

    【解决方案2】:

    我可以通过反思来做到这一点。但我想使用 DLR。

    为什么?假设这是一个实际上不会动态响应的“普通”对象,那么反射将是这里最简单的方法。

    C# 4 中的dynamic 功能(就语言 功能而言)在这里对您没有任何帮助。它只允许在 C# 源代码中动态绑定成员名称​​

    现在你可以

    • 启动 IronPython 会话,并创建一个小型 Python 脚本以使用动态绑定调用该方法。
    • 使用CSharpCodeProvider 编译一些使用dynamic 和相关方法名称的C# 代码,然后执行该代码。
    • 查看为您的d.UsersGetAll() 调用生成的代码,然后基本上进行模拟。

    所有这些选项都可能比反射更难,如果你想要它,那么在“普通”对象上调用“普通”方法,而你碰巧只在执行时知道名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 2013-09-27
      • 2012-06-18
      • 2012-09-26
      • 1970-01-01
      • 1970-01-01
      • 2012-12-20
      相关资源
      最近更新 更多