【问题标题】:Can I invoke a method on a c# dynamic using a string method name? [duplicate]我可以使用字符串方法名称在 c# 动态上调用方法吗? [复制]
【发布时间】:2013-04-18 18:41:43
【问题描述】:

我想知道是否可以通过字符串调用动态 c# 对象上的函数。我想做这样的事情:

string lMethodName = "MethodName";
dynamic lDynamicObject = GetDynamicObject();
lDynamicObject.Invoke(lMethodName, lParameters);

任何想法或解决方案将不胜感激。

也许就像 Servy 所说的,有更好的方法可以通过不同的设计来实现我们想要的。我们正在使用 SignalR 并有一个仪表板 Web 应用程序。我们希望仪表板中的每个小部件都能够将数据推送到它。为了实现这一点,我们将使用剃须刀代码将小部件 ID 注入到每个单独的小部件 SignalR 客户端代理中。每个小部件都有以下内容:

hub.client.updateWidget123456 = aUpdateFunction;

其中 123456 是小部件的 ID。在服务器端 SignalR 集线器代码中,我们可以回调客户端 javascript 函数:

int lWidgetId = 123456;
dynamic lDynamic = Clients.All;
lDynamic.Invoke("updateWidget" + lWidgetId, lParameters);

在不创建 javascript 代理方法的情况下,我可以想到其他方法来实现这一点。我认为这很好,因为服务器与每个单独的小部件都有直接的通信线路。可以从多个仪表板/浏览器访问它们,但它们都将通过上面的单个调用得到更新。

我们可以通过在我们的 javascript 客户端代码中调用其他对象来实现这一点,这些对象知道所有小部件以及如何将信息定向到它们。我觉得这违背了 SignalR 的集线器架构,就像我们这样做是在重新发明轮子。

有人对更好的设计方法有任何想法吗?感谢您的帮助,感谢您的评论 Servy 引发了这次讨论。

另外,这个问题不是重复的。另一个问题与 Paul 在下面评论的动态对象无关。

【问题讨论】:

  • 不,这个问题是针对动态类型的,另一个问题是针对一般反射的。
  • 你几乎肯定不想这样做。你应该强烈考虑重新设计你的代码,这样你就不需要这样做了。
  • 这个问题根本不是重复的,因为这里提到的另一个问题没有解决动态问题。这是关于静态类型和反射的,@Paul 已经对此发表了评论。
  • 确实 IF 您使用反射并没有什么不同,但是 OP 以及将来可能会发现这个问题的一些人正在尝试做一些“动态”的事情,并出于某种原因决定动态关键字可能是答案。显式反射只是一种类型的解决方案,并且解释确切的区别是什么,这是公认的答案是有用的。链接问题比动态关键字的引入早了一年多,该关键字首次出现在 VS2010 中。

标签: c# dynamic signalr


【解决方案1】:

如果您知道 dynamic 是一个普通的 C# 对象(即没有特殊的运行时绑定器),则只能使用反射来调用该方法。

考虑以下实现可动态使用的属性包的类:

public class PropertyBag : DynamicObject
{
    private Dictionary<string, object> _propertyBag = new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return _propertyBag.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _propertyBag[binder.Name] = value;
        return true;
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return base.GetDynamicMemberNames();
    }
}

执行以下操作是完全有效的:

dynamic propertyBag = new PropertyBag();

propertyBag.Name = "stackoverflow";
propertyBag.Value = 42;

但是,如果您尝试为这些动态属性中的任何一个获取 PropertyInfo,它将失败,因为 PropertyBag 类没有实现它们:

public static void SetProperty(dynamic propertyBag, string propertyName, object value)
{
    PropertyInfo property = propertyBag.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
    if (property == null)
    {
        throw new NotImplementedException();
    }

    MethodInfo setProperty = property.GetSetMethod();
    setProperty.Invoke(propertyBag, new object[] { value });
}

这会抛出异常:

dynamic propertyBag = new PropertyBag();

propertyBag.Name = "stackoverflow;      // works as expected
SetProperty(propertyBag, "Value", 42);  // throws a NotImplementedException

我在这个例子中使用了属性,因为它们更容易实现,但显然同样适用于方法。这样做的原因是 dynamic 在运行时动态评估,但反射只能反映在静态实现上。 (GetProperties 应该在 PropertyBag 类上返回哪些属性?)

如果您将dynamic 与普通 C# 对象一起使用,则反射将按预期工作,但如果您不知道要处理的运行时绑定器类型以及内部实现方式,则不能依赖它。

【讨论】:

    【解决方案2】:

    通过反思,我认为您可以做类似的事情(如果它是私有的 ->NonPublic)

    MethodInfo dynMethod = this.GetType().GetMethod("MethodName" + itemType, BindingFlags.NonPublic | BindingFlags.Instance);
    dynMethod.Invoke(this, new object[] { methodParams });
    

    只需使用接受 BindingFlags 的 GetMethod 的重载版本:

    【讨论】:

      【解决方案3】:

      简短的回答,是的,你可以这样做:

              class MyClass { public void Action() { Console.WriteLine("Do action"); } }
              // ...
              dynamic instance = new MyClass();
              instance.GetType().GetMethod("Action").Invoke(instance, null);
      

      但是在这种情况下,实例是动态类型这一事实绝对没有任何作用。您可以使用 object 类型,它的工作方式相同。链中的第一个方法,GetType() 返回typeof(MyClass),然后从那里开始就是普通的老式反射。

      使用动态关键字可以做到这一点,这更有趣,虽然在运行时不太灵活:

              dynamic instance = new MyClass();
              instance.Action();
      

      这将在运行时使用反射查找动作。在此示例中,dynamicvar 的工作方式不同并不是很明显,因为此处设置了 MyClass,但您可以使用第二行执行任何名为 action 的方法,只要实例具有那个名字。

      【讨论】:

        【解决方案4】:

        是的,这是可能的。您想要做的称为“反射”,并且在大多数高级语言中都可用

        这是reflection in C 的示例。它实际上非常强大,可以让你的代码在一定程度上“意识到自己”

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-07-18
          • 1970-01-01
          • 2010-11-27
          • 2018-06-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多