C# “无定义”;行动“;动态的?

C# “无定义”;行动“;动态的?,c#,exception,dynamic,C#,Exception,Dynamic,这里有一个事件,它由一个包含动态对象的参数触发。它是在事件调用本身中直接创建的匿名对象,如 if(MyEvent != null) MyEvent(this, new SensoricDataEventArgs { Data = new { Action = "Start", Team = "Blau" } }); 其中SensoricDataEventArgs的签名如下: class SensoricDataEventArgs : EventArgs { public dynamic D

这里有一个事件,它由一个包含动态对象的参数触发。它是在事件调用本身中直接创建的匿名对象,如

if(MyEvent != null) MyEvent(this, new SensoricDataEventArgs { Data = new { Action = "Start", Team = "Blau" } });
其中SensoricDataEventArgs的签名如下:

class SensoricDataEventArgs : EventArgs {
  public dynamic Data { get; set; }
}
当我尝试访问处理程序中的数据时(如果相关的话,它位于另一个程序集中),我得到的只是一个异常,即对象没有操作定义,即使我将数据属性重新转换为dynamic。甚至动态对象的DebuggerVisualizer也显示对象上存在属性操作

然而,我得到了提到的例外

下面是我试图在事件处理程序中执行的操作的图像,以及来自调试器的信息。在映像中,调试器已在断点上停止。下一步抛出异常

知道是什么导致了这个异常吗?我做错了什么?

问题在于,匿名类型被声明为
内部
,因此您试图访问的成员在其他程序集中不可见,而DLR实际上在运行时对成员可访问性执行相同的编译时分析。它不允许您在运行时访问编译时无法访问的内容。它看到匿名类型是
internal
,并抛出
RuntimeBinderException


一种解决方案是显式地编写反射代码,而不是使用
dynamic
。一个更易于维护的长期解决方案是从事件参数中删除
动态
,并更精确地定义组件之间的通信方式。

另一个解决方案是使用ExpandooObject而不是匿名对象


在我的特殊情况下,考虑到时间紧迫(截止日期临近),我将使用此解决方案,而不是重新思考我的整个体系结构,并冒着已经完成的插件不兼容的风险。它可以工作并保持兼容性

尽量避免动态,您可以使用字典而不是数据,将操作作为键,“开始”作为值。如果这不是必需的,那么您最好做一些事情,比如,创建一个带有Start、Running、Stopped…dynamic的enum操作,因为“things”的体系结构可能触发此事件,所以这里是必需的。有一个插件系统是我自己实现的,建立在它之上。啊,除此之外,我还在其他地方使用托管的IronPython/DLR,它们也基于dynamic。我在这方面支持@thefiloe。看起来你想要一个“什么都能做”的对象,它总是有点模糊,有点像是某种东西没有被正确思考的迹象。如果这些东西可以包含各种不同的数据,那么您应该看看它是如何实现的。鉴于你说你自己实现了这个插件系统,我不能相信下面我对mike回答的评论中提到的“它是强制性的”推理:),我想,我会重新考虑如何实现这个事件。。。也谢谢你!该死很抱歉嗯,好吧。。。看来我真的得重新考虑我的架构了。。。无论如何,谢谢。或者您可以使用普通命名类型。这不需要您更改体系结构,因为它将与
动态
一起工作。这就要求插件开发人员也使用普通类型。可能可以接受,但对他们来说不太舒服,因为他们必须编写更多的代码。也许我会在我们的截止日期之后再考虑这个问题,因为到时候会有更多的时间来改进这些架构缺陷。