Author:水如烟
基础类:
MethodWatcherBaseAttribute.vb
Imports System.Runtime.Remoting.Contexts
Imports System.Runtime.Remoting.Activation
Namespace uRemoting.MethodWatcher
<AttributeUsage(AttributeTargets.Class)> _
Public MustInherit Class MethodWatcherBaseAttribute
Inherits ContextAttribute
Sub New()
MyBase.New("MethodWatcherBase")
End Sub
Public Overrides Sub GetPropertiesForNewContext(ByVal ctorMsg As System.Runtime.Remoting.Activation.IConstructionCallMessage)
MethodCollection.GetAppendMethodsFromType(ctorMsg.ActivationType) '从ctorMsg中取类要绑定的方法信息
ctorMsg.ContextProperties.Add(GetMethodWatcherProperty)
End Sub
Protected MustOverride Function GetMethodWatcherProperty() As MethodWatcherBaseProperty
End Class
End Namespace
Imports System.Runtime.Remoting.Activation
Namespace uRemoting.MethodWatcher
<AttributeUsage(AttributeTargets.Class)> _
Public MustInherit Class MethodWatcherBaseAttribute
Inherits ContextAttribute
Sub New()
MyBase.New("MethodWatcherBase")
End Sub
Public Overrides Sub GetPropertiesForNewContext(ByVal ctorMsg As System.Runtime.Remoting.Activation.IConstructionCallMessage)
MethodCollection.GetAppendMethodsFromType(ctorMsg.ActivationType) '从ctorMsg中取类要绑定的方法信息
ctorMsg.ContextProperties.Add(GetMethodWatcherProperty)
End Sub
Protected MustOverride Function GetMethodWatcherProperty() As MethodWatcherBaseProperty
End Class
End Namespace
MethodWatcherBaseProperty.vb
Imports System.Runtime.Remoting.Activation
Imports System.Runtime.Remoting.Contexts
Imports System.Runtime.Remoting.Messaging
Namespace uRemoting.MethodWatcher
Public MustInherit Class MethodWatcherBaseProperty
Implements IContextProperty, IContributeObjectSink
Protected MustOverride Function CreateSink(ByVal nextSink As IMessageSink) As IMessageSink
Protected Overridable Function GetName() As String
Return Me.GetType.Name '"MethodWatcherBase"
End Function
Protected Overridable Sub FreezeImpl(ByVal newContext As Context)
Return
End Sub
Protected Overridable Function CheckNewContext(ByVal newCtx As Context) As Boolean
Return True
End Function
Public Sub Freeze(ByVal newContext As System.Runtime.Remoting.Contexts.Context) Implements System.Runtime.Remoting.Contexts.IContextProperty.Freeze
FreezeImpl(newContext)
End Sub
Public Function IsNewContextOK(ByVal newCtx As System.Runtime.Remoting.Contexts.Context) As Boolean Implements System.Runtime.Remoting.Contexts.IContextProperty.IsNewContextOK
Return CheckNewContext(newCtx)
End Function
Public ReadOnly Property Name() As String Implements System.Runtime.Remoting.Contexts.IContextProperty.Name
Get
Return GetName()
End Get
End Property
Public Function GetObjectSink(ByVal obj As System.MarshalByRefObject, ByVal nextSink As System.Runtime.Remoting.Messaging.IMessageSink) As System.Runtime.Remoting.Messaging.IMessageSink Implements System.Runtime.Remoting.Contexts.IContributeObjectSink.GetObjectSink
Return CreateSink(nextSink)
End Function
End Class
End Namespace
Imports System.Runtime.Remoting.Contexts
Imports System.Runtime.Remoting.Messaging
Namespace uRemoting.MethodWatcher
Public MustInherit Class MethodWatcherBaseProperty
Implements IContextProperty, IContributeObjectSink
Protected MustOverride Function CreateSink(ByVal nextSink As IMessageSink) As IMessageSink
Protected Overridable Function GetName() As String
Return Me.GetType.Name '"MethodWatcherBase"
End Function
Protected Overridable Sub FreezeImpl(ByVal newContext As Context)
Return
End Sub
Protected Overridable Function CheckNewContext(ByVal newCtx As Context) As Boolean
Return True
End Function
Public Sub Freeze(ByVal newContext As System.Runtime.Remoting.Contexts.Context) Implements System.Runtime.Remoting.Contexts.IContextProperty.Freeze
FreezeImpl(newContext)
End Sub
Public Function IsNewContextOK(ByVal newCtx As System.Runtime.Remoting.Contexts.Context) As Boolean Implements System.Runtime.Remoting.Contexts.IContextProperty.IsNewContextOK
Return CheckNewContext(newCtx)
End Function
Public ReadOnly Property Name() As String Implements System.Runtime.Remoting.Contexts.IContextProperty.Name
Get
Return GetName()
End Get
End Property
Public Function GetObjectSink(ByVal obj As System.MarshalByRefObject, ByVal nextSink As System.Runtime.Remoting.Messaging.IMessageSink) As System.Runtime.Remoting.Messaging.IMessageSink Implements System.Runtime.Remoting.Contexts.IContributeObjectSink.GetObjectSink
Return CreateSink(nextSink)
End Function
End Class
End Namespace
MethodWatcherBaseSink.vb
Imports System.Collections
Imports System.Runtime.Remoting.Contexts
Imports System.Runtime.Remoting.Messaging
Imports System.Runtime.Remoting.Activation
Namespace uRemoting.MethodWatcher
Public MustInherit Class MethodWatcherBaseSink
Implements IMessageSink
Private m_BeforeHandles As SortedList
Private m_AfterHandles As SortedList
Private m_NextSink As IMessageSink
Sub New(ByVal nextSink As IMessageSink)
m_NextSink = nextSink
m_BeforeHandles = New SortedList
m_AfterHandles = New SortedList
AddAllBeforeMethodCallHandles()
AddAllAfterMethodCallHandles()
End Sub
Protected Sub AddBeforeMethodCallHandle(ByVal methodName As String, ByVal beforeHandle As BeforeMethodCallHandle)
SyncLock Me.m_BeforeHandles
If Not Me.m_BeforeHandles.Contains(methodName) Then
m_BeforeHandles.Add(methodName, beforeHandle)
End If
End SyncLock
End Sub
Protected Sub AddAfterMethodCallHandle(ByVal methodName As String, ByVal afterHandle As AfterMethodCallHandle)
SyncLock Me.m_AfterHandles
If Not Me.m_AfterHandles.Contains(methodName) Then
m_AfterHandles.Add(methodName, afterHandle)
End If
End SyncLock
End Sub
Protected Sub AddAllBeforeMethodCallHandles()
For Each methodName As String In MethodCollection.DefaultInstance.Keys
If MethodCollection.DefaultInstance(methodName).GetType.Equals(MethodWatcherAppendAttributeType) Then
AddBeforeMethodCallHandle(methodName, New BeforeMethodCallHandle(AddressOf Before_MethodCall))
End If
Next
End Sub
Protected Sub AddAllAfterMethodCallHandles()
For Each methodName As String In MethodCollection.DefaultInstance.Keys
If MethodCollection.DefaultInstance(methodName).GetType.Equals(MethodWatcherAppendAttributeType) Then
AddAfterMethodCallHandle(methodName, New AfterMethodCallHandle(AddressOf After_MethodCall))
End If
Next
End Sub
Protected Overridable Sub Before_MethodCall(ByVal callMsg As IMethodCallMessage, ByVal MethodAppendType As System.Type)
If callMsg Is Nothing Then
Return
End If
MethodWatcherCenter.ReceiveBeforeMethodCallEvent(callMsg, MethodAppendType)
End Sub
Protected Overridable Sub After_MethodCall(ByVal replyMsg As IMethodReturnMessage, ByVal MethodAppendType As System.Type)
If replyMsg Is Nothing Then
Return
End If
MethodWatcherCenter.ReceiveAfterMethodCallEvent(replyMsg, MethodAppendType)
End Sub
Protected MustOverride ReadOnly Property MethodWatcherAppendAttributeType() As Type
Protected Function FindBeforeMethodCallHandle(ByVal methodName As String) As BeforeMethodCallHandle
Dim beforeHandle As BeforeMethodCallHandle
SyncLock Me.m_BeforeHandles
beforeHandle = CType(m_BeforeHandles(methodName), BeforeMethodCallHandle)
End SyncLock
Return beforeHandle
End Function
Protected Function FindAfterMethodCallHandle(ByVal methodName As String) As AfterMethodCallHandle
Dim afterHandle As AfterMethodCallHandle
SyncLock Me.m_AfterHandles
afterHandle = CType(m_AfterHandles(methodName), AfterMethodCallHandle)
End SyncLock
Return afterHandle
End Function
Public Function AsyncProcessMessage(ByVal msg As System.Runtime.Remoting.Messaging.IMessage, ByVal replySink As System.Runtime.Remoting.Messaging.IMessageSink) As System.Runtime.Remoting.Messaging.IMessageCtrl Implements System.Runtime.Remoting.Messaging.IMessageSink.AsyncProcessMessage
Return Nothing
End Function
Public ReadOnly Property NextSink() As System.Runtime.Remoting.Messaging.IMessageSink Implements System.Runtime.Remoting.Messaging.IMessageSink.NextSink
Get
Return m_NextSink
End Get
End Property
Public Function SyncProcessMessage(ByVal msg As System.Runtime.Remoting.Messaging.IMessage) As System.Runtime.Remoting.Messaging.IMessage Implements System.Runtime.Remoting.Messaging.IMessageSink.SyncProcessMessage
Dim [call] As IMethodCallMessage = CType(msg, IMethodCallMessage)
Dim methodName As String = MethodWatcherCommon.GetFullMethodName(msg, MethodWatcherAppendAttributeType) '这里取全名
Dim beforeHandle As BeforeMethodCallHandle = FindBeforeMethodCallHandle(methodName)
If beforeHandle IsNot Nothing Then
beforeHandle([call], MethodWatcherAppendAttributeType)
End If
Dim retMsg As System.Runtime.Remoting.Messaging.IMessage = m_NextSink.SyncProcessMessage(msg)
Dim reply As IMethodReturnMessage = CType(retMsg, IMethodReturnMessage)
Dim afterHandle As AfterMethodCallHandle = FindAfterMethodCallHandle(methodName)
If afterHandle IsNot Nothing Then
afterHandle(reply, MethodWatcherAppendAttributeType)
End If
Return retMsg
End Function
End Class
End Namespace
Imports System.Runtime.Remoting.Contexts
Imports System.Runtime.Remoting.Messaging
Imports System.Runtime.Remoting.Activation
Namespace uRemoting.MethodWatcher
Public MustInherit Class MethodWatcherBaseSink
Implements IMessageSink
Private m_BeforeHandles As SortedList
Private m_AfterHandles As SortedList
Private m_NextSink As IMessageSink
Sub New(ByVal nextSink As IMessageSink)
m_NextSink = nextSink
m_BeforeHandles = New SortedList
m_AfterHandles = New SortedList
AddAllBeforeMethodCallHandles()
AddAllAfterMethodCallHandles()
End Sub
Protected Sub AddBeforeMethodCallHandle(ByVal methodName As String, ByVal beforeHandle As BeforeMethodCallHandle)
SyncLock Me.m_BeforeHandles
If Not Me.m_BeforeHandles.Contains(methodName) Then
m_BeforeHandles.Add(methodName, beforeHandle)
End If
End SyncLock
End Sub
Protected Sub AddAfterMethodCallHandle(ByVal methodName As String, ByVal afterHandle As AfterMethodCallHandle)
SyncLock Me.m_AfterHandles
If Not Me.m_AfterHandles.Contains(methodName) Then
m_AfterHandles.Add(methodName, afterHandle)
End If
End SyncLock
End Sub
Protected Sub AddAllBeforeMethodCallHandles()
For Each methodName As String In MethodCollection.DefaultInstance.Keys
If MethodCollection.DefaultInstance(methodName).GetType.Equals(MethodWatcherAppendAttributeType) Then
AddBeforeMethodCallHandle(methodName, New BeforeMethodCallHandle(AddressOf Before_MethodCall))
End If
Next
End Sub
Protected Sub AddAllAfterMethodCallHandles()
For Each methodName As String In MethodCollection.DefaultInstance.Keys
If MethodCollection.DefaultInstance(methodName).GetType.Equals(MethodWatcherAppendAttributeType) Then
AddAfterMethodCallHandle(methodName, New AfterMethodCallHandle(AddressOf After_MethodCall))
End If
Next
End Sub
Protected Overridable Sub Before_MethodCall(ByVal callMsg As IMethodCallMessage, ByVal MethodAppendType As System.Type)
If callMsg Is Nothing Then
Return
End If
MethodWatcherCenter.ReceiveBeforeMethodCallEvent(callMsg, MethodAppendType)
End Sub
Protected Overridable Sub After_MethodCall(ByVal replyMsg As IMethodReturnMessage, ByVal MethodAppendType As System.Type)
If replyMsg Is Nothing Then
Return
End If
MethodWatcherCenter.ReceiveAfterMethodCallEvent(replyMsg, MethodAppendType)
End Sub
Protected MustOverride ReadOnly Property MethodWatcherAppendAttributeType() As Type
Protected Function FindBeforeMethodCallHandle(ByVal methodName As String) As BeforeMethodCallHandle
Dim beforeHandle As BeforeMethodCallHandle
SyncLock Me.m_BeforeHandles
beforeHandle = CType(m_BeforeHandles(methodName), BeforeMethodCallHandle)
End SyncLock
Return beforeHandle
End Function
Protected Function FindAfterMethodCallHandle(ByVal methodName As String) As AfterMethodCallHandle
Dim afterHandle As AfterMethodCallHandle
SyncLock Me.m_AfterHandles
afterHandle = CType(m_AfterHandles(methodName), AfterMethodCallHandle)
End SyncLock
Return afterHandle
End Function
Public Function AsyncProcessMessage(ByVal msg As System.Runtime.Remoting.Messaging.IMessage, ByVal replySink As System.Runtime.Remoting.Messaging.IMessageSink) As System.Runtime.Remoting.Messaging.IMessageCtrl Implements System.Runtime.Remoting.Messaging.IMessageSink.AsyncProcessMessage
Return Nothing
End Function
Public ReadOnly Property NextSink() As System.Runtime.Remoting.Messaging.IMessageSink Implements System.Runtime.Remoting.Messaging.IMessageSink.NextSink
Get
Return m_NextSink
End Get
End Property
Public Function SyncProcessMessage(ByVal msg As System.Runtime.Remoting.Messaging.IMessage) As System.Runtime.Remoting.Messaging.IMessage Implements System.Runtime.Remoting.Messaging.IMessageSink.SyncProcessMessage
Dim [call] As IMethodCallMessage = CType(msg, IMethodCallMessage)
Dim methodName As String = MethodWatcherCommon.GetFullMethodName(msg, MethodWatcherAppendAttributeType) '这里取全名
Dim beforeHandle As BeforeMethodCallHandle = FindBeforeMethodCallHandle(methodName)
If beforeHandle IsNot Nothing Then
beforeHandle([call], MethodWatcherAppendAttributeType)
End If
Dim retMsg As System.Runtime.Remoting.Messaging.IMessage = m_NextSink.SyncProcessMessage(msg)
Dim reply As IMethodReturnMessage = CType(retMsg, IMethodReturnMessage)
Dim afterHandle As AfterMethodCallHandle = FindAfterMethodCallHandle(methodName)
If afterHandle IsNot Nothing Then
afterHandle(reply, MethodWatcherAppendAttributeType)
End If
Return retMsg
End Function
End Class
End Namespace
MethodWatcherDelegate.vb
Imports System.Runtime.Remoting.Messaging
Namespace uRemoting.MethodWatcher
Public Delegate Sub BeforeMethodCallHandle(ByVal callMsg As IMethodCallMessage, ByVal MethodAppendType As System.Type)
Public Delegate Sub AfterMethodCallHandle(ByVal replyMsg As IMethodReturnMessage, ByVal MethodAppendType As System.Type)
End Namespace
Namespace uRemoting.MethodWatcher
Public Delegate Sub BeforeMethodCallHandle(ByVal callMsg As IMethodCallMessage, ByVal MethodAppendType As System.Type)
Public Delegate Sub AfterMethodCallHandle(ByVal replyMsg As IMethodReturnMessage, ByVal MethodAppendType As System.Type)
End Namespace
MethodWatcherAppendBaseAttribute.vb
Namespace uRemoting.MethodWatcher
<AttributeUsage(AttributeTargets.Class, allowmultiple:=True)> _
Public MustInherit Class MethodWatcherAppendBaseAttribute
Inherits Attribute
Private gMethodName As String
Private gWatchContextType As System.Type
Sub New(ByVal methodName As String)
gMethodName = methodName
End Sub
Public Property MethodName() As String
Get
Return gMethodName
End Get
Set(ByVal value As String)
gMethodName = value
End Set
End Property
Public Sub SetContextType(ByVal contextType As System.Type)
gWatchContextType = contextType
End Sub
Public ReadOnly Property FullMethodName() As String
Get
Return MethodWatcherCommon.GetFullMethodName(gWatchContextType, MethodName, Me.GetType)
End Get
End Property
End Class
End Namespace
<AttributeUsage(AttributeTargets.Class, allowmultiple:=True)> _
Public MustInherit Class MethodWatcherAppendBaseAttribute
Inherits Attribute
Private gMethodName As String
Private gWatchContextType As System.Type
Sub New(ByVal methodName As String)
gMethodName = methodName
End Sub
Public Property MethodName() As String
Get
Return gMethodName
End Get
Set(ByVal value As String)
gMethodName = value
End Set
End Property
Public Sub SetContextType(ByVal contextType As System.Type)
gWatchContextType = contextType
End Sub
Public ReadOnly Property FullMethodName() As String
Get
Return MethodWatcherCommon.GetFullMethodName(gWatchContextType, MethodName, Me.GetType)
End Get
End Property
End Class
End Namespace
基础实现:
MethodCollection.vb
Namespace uRemoting.MethodWatcher
Friend Class MethodCollection
Inherits Dictionary(Of String, MethodWatcherAppendBaseAttribute)
Private Shared gCollection As MethodCollection
Shared Sub New()
gCollection = New MethodCollection
End Sub
Private Sub New()
End Sub
Public Shared ReadOnly Property DefaultInstance() As MethodCollection
Get
Return gCollection
End Get
End Property
Public Shared Sub GetAppendMethodsFromType(ByVal contextType As Type)
For Each tmpCustomAttribute As Object In contextType.GetCustomAttributes(True)
If tmpCustomAttribute.GetType.BaseType Is GetType(MethodWatcherAppendBaseAttribute) Then
Dim tmpAppendAttribute As MethodWatcherAppendBaseAttribute = CType(tmpCustomAttribute, MethodWatcherAppendBaseAttribute)
tmpAppendAttribute.SetContextType(contextType)
SyncLock gCollection
If Not DefaultInstance.ContainsKey(tmpAppendAttribute.FullMethodName) Then
DefaultInstance.Add(tmpAppendAttribute.FullMethodName, tmpAppendAttribute)
End If
End SyncLock
End If
Next
End Sub
End Class
End Namespace
Friend Class MethodCollection
Inherits Dictionary(Of String, MethodWatcherAppendBaseAttribute)
Private Shared gCollection As MethodCollection
Shared Sub New()
gCollection = New MethodCollection
End Sub
Private Sub New()
End Sub
Public Shared ReadOnly Property DefaultInstance() As MethodCollection
Get
Return gCollection
End Get
End Property
Public Shared Sub GetAppendMethodsFromType(ByVal contextType As Type)
For Each tmpCustomAttribute As Object In contextType.GetCustomAttributes(True)
If tmpCustomAttribute.GetType.BaseType Is GetType(MethodWatcherAppendBaseAttribute) Then
Dim tmpAppendAttribute As MethodWatcherAppendBaseAttribute = CType(tmpCustomAttribute, MethodWatcherAppendBaseAttribute)
tmpAppendAttribute.SetContextType(contextType)
SyncLock gCollection
If Not DefaultInstance.ContainsKey(tmpAppendAttribute.FullMethodName) Then
DefaultInstance.Add(tmpAppendAttribute.FullMethodName, tmpAppendAttribute)
End If
End SyncLock
End If
Next
End Sub
End Class
End Namespace
MethodWatcherCommon.vb
Namespace uRemoting.MethodWatcher
Friend Class MethodWatcherCommon
Private Sub New()
End Sub
Public Shared Function GetFullMethodName(ByVal contextType As System.Type, ByVal methodName As String, ByVal MeathodAppendAttibuteType As System.Type) As String
Return String.Format("{0}+{1}:{2}", contextType.FullName, methodName, MeathodAppendAttibuteType.Name)
End Function
Public Shared Function GetFullMethodName(ByVal msg As System.Runtime.Remoting.Messaging.IMessage, ByVal MethodAppendType As System.Type) As String
Dim tmpType As Type = Type.GetType(msg.Properties("__TypeName").ToString)
Dim tmpMethodName As String = msg.Properties("__MethodName").ToString
Return GetFullMethodName(tmpType, tmpMethodName, MethodAppendType)
End Function
Public Shared Function GetFullMethodName(ByVal callMsg As System.Runtime.Remoting.Messaging.IMethodCallMessage, ByVal MethodAppendType As System.Type) As String
Return GetFullMethodName(CType(callMsg, System.Runtime.Remoting.Messaging.IMessage), MethodAppendType)
End Function
Public Shared Function GetFullMethodName(ByVal replyMsg As System.Runtime.Remoting.Messaging.IMethodReturnMessage, ByVal MethodAppendType As System.Type) As String
Return GetFullMethodName(CType(replyMsg, System.Runtime.Remoting.Messaging.IMessage), MethodAppendType)
End Function
End Class
End Namespace
Friend Class MethodWatcherCommon
Private Sub New()
End Sub
Public Shared Function GetFullMethodName(ByVal contextType As System.Type, ByVal methodName As String, ByVal MeathodAppendAttibuteType As System.Type) As String
Return String.Format("{0}+{1}:{2}", contextType.FullName, methodName, MeathodAppendAttibuteType.Name)
End Function
Public Shared Function GetFullMethodName(ByVal msg As System.Runtime.Remoting.Messaging.IMessage, ByVal MethodAppendType As System.Type) As String
Dim tmpType As Type = Type.GetType(msg.Properties("__TypeName").ToString)
Dim tmpMethodName As String = msg.Properties("__MethodName").ToString
Return GetFullMethodName(tmpType, tmpMethodName, MethodAppendType)
End Function
Public Shared Function GetFullMethodName(ByVal callMsg As System.Runtime.Remoting.Messaging.IMethodCallMessage, ByVal MethodAppendType As System.Type) As String
Return GetFullMethodName(CType(callMsg, System.Runtime.Remoting.Messaging.IMessage), MethodAppendType)
End Function
Public Shared Function GetFullMethodName(ByVal replyMsg As System.Runtime.Remoting.Messaging.IMethodReturnMessage, ByVal MethodAppendType As System.Type) As String
Return GetFullMethodName(CType(replyMsg, System.Runtime.Remoting.Messaging.IMessage), MethodAppendType)
End Function
End Class
End Namespace
MethodWatcherCenter.vb
Imports System.Runtime.Remoting.Messaging
Namespace uRemoting.MethodWatcher
Public Class MethodWatcherCenter
Public Shared Event MethodCallBegin As BeforeMethodCallHandle
Public Shared Event MethodCallOver As AfterMethodCallHandle
Friend Shared Sub ReceiveBeforeMethodCallEvent(ByVal callMsg As IMethodCallMessage, ByVal MethodAppendType As System.Type)
RaiseEvent MethodCallBegin(callMsg, MethodAppendType)
End Sub
Friend Shared Sub ReceiveAfterMethodCallEvent(ByVal replyMsg As IMethodReturnMessage, ByVal MethodAppendType As System.Type)
RaiseEvent MethodCallOver(replyMsg, MethodAppendType)
End Sub
End Class
End Namespace
Namespace uRemoting.MethodWatcher
Public Class MethodWatcherCenter
Public Shared Event MethodCallBegin As BeforeMethodCallHandle
Public Shared Event MethodCallOver As AfterMethodCallHandle
Friend Shared Sub ReceiveBeforeMethodCallEvent(ByVal callMsg As IMethodCallMessage, ByVal MethodAppendType As System.Type)
RaiseEvent MethodCallBegin(callMsg, MethodAppendType)
End Sub
Friend Shared Sub ReceiveAfterMethodCallEvent(ByVal replyMsg As IMethodReturnMessage, ByVal MethodAppendType As System.Type)
RaiseEvent MethodCallOver(replyMsg, MethodAppendType)
End Sub
End Class
End Namespace