Author:水如烟
有关见异类HOW TO:适时弹出指示框(汇总) .
现在重列基类代码,是因为作了一些改动.在下文中,将继承这些类作一个示例:代码如社会般,暗处有玄机。所以,NET说ContextBoundObject是不用用户使用的,是有道理的。代码本身不作说明,因为自己也不懂。
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()
End Sub
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
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
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
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
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
MethodCollection.vb
Namespace uRemoting.MethodWatcher
Friend Class MethodCollection
Inherits Dictionary(Of String, MethodWatcherAppendBaseAttribute)
Private Shared gCollection As MethodCollection
Shared Sub New()
gCollection = New MethodCollection
gContextBoundObjctMethods = New Dictionary(Of String, Object)
For Each m As Reflection.MethodInfo In GetType(ContextBoundObject).GetMethods
gContextBoundObjctMethods.Add(m.Name, Nothing)
Next
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)
If tmpAppendAttribute.MethodName = "" Then
For Each m As Reflection.MemberInfo In contextType.GetMethods
If Not gContextBoundObjctMethods.ContainsKey(m.Name) Then
tmpAppendAttribute.MethodName = m.Name
AddMethod(tmpAppendAttribute)
End If
Next
Else
AddMethod(tmpAppendAttribute)
End If
End If
Next
End Sub
Private Shared Sub AddMethod(ByVal methodAppendAttibute As MethodWatcherAppendBaseAttribute)
SyncLock gCollection
If Not DefaultInstance.ContainsKey(methodAppendAttibute.FullMethodName) Then
DefaultInstance.Add(methodAppendAttibute.FullMethodName, methodAppendAttibute)
End If
End SyncLock
End Sub
Private Shared gContextBoundObjctMethods As Dictionary(Of String, Object)
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
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
一个简单的Watcher:SimpleMethodWatcher
SimpleMethodWatcherAppendAttribute.vb
Namespace uRemoting.MethodWatcher
<AttributeUsage(AttributeTargets.Class, allowmultiple:=True)> _
Public NotInheritable Class SimpleMethodWatcherAppendAttribute
Inherits MethodWatcherAppendBaseAttribute
Sub New()
End Sub
Sub New(ByVal methodName As String)
MyBase.New(methodName)
End Sub
End Class
End Namespace
SimpleMethodWatcherAttribute.vb
Namespace uRemoting.MethodWatcher
<AttributeUsage(AttributeTargets.Class)> _
Public Class SimpleMethodWatcherAttribute
Inherits MethodWatcherBaseAttribute
Protected Overrides Function GetMethodWatcherProperty() As MethodWatcherBaseProperty
Return New SimpleMethodWatcherProperty
End Function
End Class
End Namespace
SimpleMethodWatcherCenter.vb
Imports System.Runtime.Remoting.Messaging
Namespace uRemoting.MethodWatcher
Public Class SimpleMethodWatcherCenter
Inherits MethodWatcherCenter
Public Sub Ready()
Remove()
AddHandler MethodCallBegin, New BeforeMethodCallHandle(AddressOf WriteMethodCallBegin)
AddHandler MethodCallOver, New AfterMethodCallHandle(AddressOf WriteMethodCallOver)
End Sub
Public Sub Remove()
RemoveHandler MethodCallBegin, New BeforeMethodCallHandle(AddressOf WriteMethodCallBegin)
RemoveHandler MethodCallOver, New AfterMethodCallHandle(AddressOf WriteMethodCallOver)
End Sub
Protected Overridable Sub WriteMethodCallBegin(ByVal callMsg As IMethodCallMessage, ByVal MethodAppendType As System.Type)
If MethodAppendType.Equals(GetType(SimpleMethodWatcherAppendAttribute)) Then
Else
End If
End Sub
Protected Overridable Sub WriteMethodCallOver(ByVal replyMsg As IMethodReturnMessage, ByVal MethodAppendType As System.Type)
If MethodAppendType.Equals(GetType(SimpleMethodWatcherAppendAttribute)) Then
Else
End If
End Sub
End Class
End Namespace
SimpleMethodWatcherProperty.vb
Namespace uRemoting.MethodWatcher
Public Class SimpleMethodWatcherProperty
Inherits MethodWatcherBaseProperty
Protected Overrides Function CreateSink(ByVal nextSink As System.Runtime.Remoting.Messaging.IMessageSink) As System.Runtime.Remoting.Messaging.IMessageSink
Return New SimpleMethodWatcherSink(nextSink)
End Function
End Class
End Namespace
SimpleMethodWatcherSink.vb
Imports System.Runtime.Remoting.Messaging
Namespace uRemoting.MethodWatcher
Public Class SimpleMethodWatcherSink
Inherits MethodWatcherBaseSink
Sub New(ByVal nextSink As IMessageSink)
MyBase.New(nextSink)
End Sub
Protected Overrides ReadOnly Property MethodWatcherAppendAttributeType() As System.Type
Get
Return GetType(SimpleMethodWatcherAppendAttribute)
End Get
End Property
End Class
End Namespace