如何在运行时向方法添加属性?

14
我们在应用程序中使用 Microsoft.Practices.CompositeUI.EventBroker 来处理事件订阅和发布。其工作方式是,您需要向事件添加一个属性,指定主题名称,例如:

我们在应用程序中使用 Microsoft.Practices.CompositeUI.EventBroker 来处理事件订阅和发布。其工作方式是,您需要向事件添加一个属性,指定主题名称,例如:

[EventPublication("example", PublicationScope.Global)]
public event EventHandler Example;

然后您向处理程序添加另一个属性,与相同的主题名称,就像这样:

[EventSubscription("example", ThreadOption.Publisher)]
public void OnExample(object sender, EventArgs e)
{
    ...
}

然后,您将对象传递给事件检查器,使其进行匹配。

我们需要对此进行调试,因此我们正在尝试创建一个订阅所有事件的调试类。我可以获取所有主题名称的列表...但仅在运行时。因此,在将调试对象传递给EventInspector之前,我需要能够在运行时向方法添加属性。

如何在运行时向方法添加属性?


顺便问一下:请告诉我们你是如何做到的,哈哈。 - Bogdan Maxim
4个回答

11
您正在尝试实现的内容相当复杂,因此我将尝试提供一些初始信息。以下是我认为您需要结合使用才能实现它的内容:
  1. 定义一个抽象类AbstractEventDebugger,其中包含一个Search方法,该方法搜索所有的event成员,并向EventInspector注册它们。还要定义一个IdentifyEvent方法,以允许您识别调用它的事件(这取决于参数等)。
  2. 使用TypeBuilder(如此处所述)定义一个动态类型,该类型继承自您的类。此类将是您的debugger对象的类。
  3. 使用Reflection.Emit.MethodBuilder将处理程序附加到您的类上(请参见此处),该处理程序将从父类中调用IdentifyEvent方法,
  4. 使用CustomAttributeBuilder类(请参见此处)在处理程序上反射发出属性。
  5. 创建您的dynamic类的实例,并将其发送到EventInspector。
  6. 启动它 :)
此处是一个示例,说明如何创建调用某些内容的方法(实际上,这是经典的“Hello world”)。
为了完成它,您需要进行大量微调,但是您将学习很多关于反射的知识。
祝你好运!

+1 表示提供实际解决方案,而不是“无法完成”。谢谢。 - marknuzz

3

属性是编译时的特性(除非你正在处理 ComponentModel - 但我猜它使用反射)。因此,您无法在运行时添加属性。这类似于“如何在运行时向类型添加额外的方法?”。在常规的 C# / .NET(DLR 之前),您无法实现。


实际上,可以通过混合动态程序集和普通程序集来完成。.NET 2.0支持它们,您不需要仅为此使用DLR。 - Bogdan Maxim
3
@Bogdan - 但这仍然不允许您向现有类型/成员添加属性。 - Marc Gravell

1
你需要深入了解DynamicMethod的世界。然而,由于你需要了解MSIL,我真的建议你认真考虑你的架构。

1
也许他的架构是动态的,旨在在运行时为多种类型提供服务。这并不罕见,实际上如果你想拥有一个模块化系统,这是推荐的做法。 - Bogdan Maxim

1
EventInspector使用存储在WorkItem中的EventTopics来完成所有繁重的工作。每个EventTopic对象都可以访问一个名为TraceSource的跟踪源。

Microsoft.Practices.CompositeUI.EventBroker.EventTopic

你可以在你的 app.config 文件中像这样启用它:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.diagnostics>
        <switches>
            <add name="Microsoft.Practices.CompositeUI.EventBroker.EventTopic" value="All" />
        </switches>
    </system.diagnostics>
</configuration>

这样做应该会将许多有用的消息路由到您在Visual Studio中的调试窗口。如果您想超越VS调试窗口,您有很多选择。我建议查看以下文章:

使用TraceSource进行代码插装 My Persoanl Vade Mecum


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