1

我正在寻找一种在运行时向类添加接口实现的方法。这是一个示例代码,我将在下面讨论。

Public Interface IAction
    Sub DoThis(a As Integer)
End Interface


Class Actor
Implements IAction

    Private mNumber As Integer

    Public Sub New(number As Integer)
        mNumber = number
    End Sub

    Public Sub DoThis(a As Integer) Implements IAction.DoThis
        Console.WriteLine(String.Format("Actor #{0}: {1}", mNumber, a))
    End Sub

End Class


Class ActionDispatcher
Implements IAction

    Private Shared mActionList As New List(Of IAction)

    Public Shared Sub Add(actor As IAction)
        mActionList.Add(actor)
    End Sub

    Public Sub DoThis(a As Integer) Implements IAction.DoThis
        For Each act In mActionList
            act.DoThis(a)
        Next
    End Sub

End Class


Module Module1

    Sub Main()
        Dim a As New ActionDispatcher
        ActionDispatcher.Add(New Actor(1))
        ActionDispatcher.Add(New Actor(2))
        a.DoThis(5)
    End Sub

End Module

这与 WCF 相关,需要向 CreateHost 提供单个类,该类实现端点所需的所有接口。在这个场景中,ActionDispatcher 就是这样一个类,而 IAction 就是众多要实现的接口之一。

我的愿景是避免在 ActionDispatcher 中手动实现 IAction,但有某种注册机制,我可以说,ActionDispatcher 必须实现接口 IAction、IDoing、INoAction 等 - 并为我生成调度方法。

MSDN 说,任何类都兼容任何接口,所以我不需要在 ActionDispatcher 中声明“Implements”。但是我仍然需要实现接口,并将实现方法连接到接口定义上,以便 WCF 可以在需要时找到它。

我发现的最接近的可能是Automatic Interface Implementer,但它 (1) 创建了一个新类型,(2) 添加了虚拟方法。

我也试图理解 CodeCompileUnit 类,但到目前为止还看不到与我需要的关系。

在反射 API 方面更有经验的人可以帮助我吗?有什么好方法可以做我想做的事吗?

4

4 回答 4

2

我终于把它咬碎了。对于那些对复杂性感兴趣的人,解决方案(简而言之)是:

Class ActionDispatcher

    Private Shared mImplementorType As Type

    Public Shared Function GetImplementorType() As Type
        If mImplementorType Is Nothing
            mImplementorType = CreateImplementorType()
        End If

        Return mImplementorType
    End Function

    Private Shared Function CreateImplementorType() As Type
        ' Nice to have RunAndSave for debugging with ILdasm / ILSpy
        Dim myAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
            New AssemblyName() With { .Name = "ViewerDispatcherAssembly" },
            AssemblyBuilderAccess.RunAndSave)
        Dim mbuilder = myAssemblyBuilder.DefineDynamicModule("ViewerDispatcherModule", "ViewerDispatcherModule.dll")
        Dim tbuilder = mbuilder.DefineType("ViewerDispatcherImpl", TypeAttributes.Class Or TypeAttributes.Public)

        For Each itype In mInterfaceTypes
            tbuilder.AddInterfaceImplementation(itype)
            For Each method In itype.GetMethods()
                ' Create interface implementation for each interface method.
                CreateInterfaceImplementation(tbuilder, itype, method, capability, mbuilder)
            Next
        Next
        Return tbuilder.CreateType()
    End Sub
End Class

该函数CreateInterfaceImplementation动态创建一个类型来保存接口参数,并在此类型中创建一个方法来调用正确的IAction函数。它还IActiontbuilder. 还存在一个中间函数来循环mActionList以最小化生成的代码量。

于 2012-05-10T13:07:25.170 回答
0

您可以使用 Castle Dynamic Proxy 尝试某种混合。 http://www.codeproject.com/Articles/9055/Castle-s-DynamicProxy-for-NET 还创建了一个新类型(代理),所以也许你也不喜欢它......

于 2012-05-07T21:44:10.207 回答
0

首先,这似乎需要大量工作来避免几行代码。如果您希望一个类实现一个接口,只需指定它,这就是 .Net 类型系统的工作方式。

事实上,你不能真正做你想做的事。您不能在运行时修改类的代码。您可以期望的最好的结果是创建一个实现接口的新类型。但是,如果您不想在运行时创建新类型(为什么?),那么我认为您不走运。

于 2012-05-07T12:42:40.837 回答
0

我听说过使用反射来编写属性值,但在运行时将新属性和方法注入现有类型?对我来说听起来有点太未来了。

即使有可能,接口也用于定义一组属性和/或方法,这些属性和/或方法始终存在于实现它们的类型中。如果您确实可以随意添加或删除实现,那么它很可能会破坏以某种方式依赖您的类的任何其他类型。

于 2012-05-07T16:39:47.007 回答