Imports System.Reflection Imports System.Runtime.Remoting Imports System.Runtime.Remoting.Channels Imports System.Runtime.Remoting.Channels.Http 'case 1012 Imports System.Runtime.Serialization.Formatters.Binary Imports System.IO.Compression Imports System.IO 'Imports System.Configuration ''' ''' This is the client-side DataPortal as described in ''' Chapter 5. ''' Public Class DataPortal Private Shared mPortalRemote As Boolean = False Public Shared mIsRemote As Boolean = False Private Shared mInitialized As Boolean = False Public Shared mPortalString As String = "" #Region " Data Access methods " ''' ''' Called by a factory method in a business class to create ''' a new object, which is loaded with default ''' values from the database. ''' ''' Object-specific criteria. ''' A new object, populated with default values. Public Shared Function Create(ByVal Criteria As Object) As Object Dim obj As Object Dim method As MethodInfo = GetMethod(GetObjectType(Criteria), "DataPortal_Create") Dim forceLocal As Boolean = RunLocal(method) 'If IsTransactionalMethod(method) Then ' 'obj = ServicedPortal(forceLocal).Create(Criteria, _ ' ' New Server.DataPortalContext(GetPrincipal, mPortalRemote AndAlso Not forceLocal)) 'Else obj = Portal(forceLocal).Create(Criteria, _ New Server.DataPortalContext(GetPrincipal, mPortalRemote AndAlso Not forceLocal)) 'End If If mPortalRemote AndAlso Not forceLocal Then Serialization.SerializationNotification.OnDeserialized(obj) End If Return obj End Function ''' ''' Called by a factory method in a business class to retrieve ''' an object, which is loaded with values from the database. ''' ''' Object-specific criteria. ''' An object populated with values from the database. Public Shared Function Fetch(ByVal Criteria As Object) As Object Init() Dim obj As Object Dim method As MethodInfo = GetMethod(GetObjectType(Criteria), "DataPortal_Fetch") Dim forceLocal As Boolean = RunLocal(method) obj = Portal(forceLocal).Fetch(Criteria, _ New Server.DataPortalContext(GetPrincipal, mPortalRemote AndAlso Not forceLocal)) 'If mPortalRemote AndAlso Not forceLocal Then ' Serialization.SerializationNotification.OnDeserialized(obj) 'End If If mPortalRemote Then obj = Decompress(DirectCast(obj, Byte())) End If Return obj End Function ''' ''' Called by the method to ''' insert, update or delete an object in the database. ''' ''' ''' Note that this method returns a reference to the updated business object. ''' If the server-side DataPortal is running remotely, this will be a new and ''' different object from the original, and all object references MUST be updated ''' to use this new object. ''' ''' A reference to the business object to be updated. ''' A reference to the updated business object. Public Shared Function Update(ByVal obj As Object) As Object Dim updated As Object Dim method As MethodInfo = GetMethod(obj.GetType, "DataPortal_Update") Dim forceLocal As Boolean = RunLocal(method) Dim canCompress As Boolean = True 'case 1012 If mPortalRemote AndAlso canCompress Then 'It's going to the server remotely so compress it 'Note servicebank can't be compressed due to transaction object not being serializable If (obj.GetType().ToString() <> "GZTW.AyaNova.BLL.ServiceBank") Then obj = Compress(obj) Else canCompress = False End If End If updated = Portal(forceLocal).Update(obj, _ New Server.DataPortalContext(GetPrincipal, mPortalRemote)) 'case 1012 If mPortalRemote AndAlso canCompress Then 'It came from the server compressed so decompress it Return Decompress(DirectCast(updated, Byte())) Else Return updated End If Return updated End Function ''' ''' Called by a Shared method in the business class to cause ''' immediate deletion of a specific object from the database. ''' ''' Object-specific criteria. Public Shared Sub Delete(ByVal Criteria As Object) Dim method As MethodInfo = GetMethod(GetObjectType(Criteria), "DataPortal_Delete") Dim forceLocal As Boolean = RunLocal(method) 'If IsTransactionalMethod(method) Then ' ServicedPortal(forceLocal).Delete(Criteria, _ ' New Server.DataPortalContext(GetPrincipal, mPortalRemote AndAlso Not forceLocal)) 'Else Portal(forceLocal).Delete(Criteria, _ New Server.DataPortalContext(GetPrincipal, mPortalRemote AndAlso Not forceLocal)) ' End If End Sub #End Region #Region "Compression" 'case 1012 Private Shared bSerializer As New BinaryFormatter Public Shared Function Compress(ByVal obj As Object) As Byte() Dim ms3 As New MemoryStream Dim cmp3 As New GZipStream(ms3, CompressionMode.Compress, False) bSerializer.Serialize(cmp3, obj) cmp3.Flush() cmp3.Close() Return ms3.ToArray() End Function Public Shared Function Decompress(ByVal bytes() As Byte) As Object Dim ms4 As New MemoryStream(bytes) Dim cmp4 As New GZipStream(ms4, CompressionMode.Decompress) Dim o As Object = bSerializer.Deserialize(cmp4) Return o End Function #End Region #Region " Server-side DataPortal " Private Shared mPortal As Server.DataPortal ' Private Shared mServicedPortal As Server.ServicedDataPortal.DataPortal Private Shared mRemotePortal As Server.DataPortal ' Private Shared mRemoteServicedPortal As Server.ServicedDataPortal.DataPortal Private Shared Function Portal(ByVal forceLocal As Boolean) As Server.DataPortal If Not forceLocal AndAlso mPortalRemote Then ' return remote instance If mRemotePortal Is Nothing Then mRemotePortal = CType(Activator.GetObject(GetType(Server.DataPortal), mPortalString), _ Server.DataPortal) End If Return mRemotePortal Else ' return local instance If mPortal Is Nothing Then mPortal = New Server.DataPortal() End If Return mPortal End If End Function 'Private Shared Function ServicedPortal(ByVal forceLocal As Boolean) As Server.ServicedDataPortal.DataPortal ' If Not forceLocal AndAlso mPortalRemote Then ' ' return remote instance ' If mRemoteServicedPortal Is Nothing Then ' mRemoteServicedPortal = _ ' CType(Activator.GetObject(GetType(Server.ServicedDataPortal.DataPortal), _ ' SERVICED_PORTAL_SERVER), _ ' Server.ServicedDataPortal.DataPortal) ' End If ' Return mRemoteServicedPortal ' Else ' ' return local instance ' If mServicedPortal Is Nothing Then ' mServicedPortal = New Server.ServicedDataPortal.DataPortal() ' End If ' Return mServicedPortal ' End If 'End Function 'Private Shared Function PORTAL_SERVER() As String ' Return "XXX" 'System.CXXXonfiguration.ConfigurationManager.AppSettings("PortalServer") 'End Function 'Private Shared Function SERVICED_PORTAL_SERVER() As String ' Return "" 'System.CXXXonfiguration.ConfigurationManager.AppSettings("ServicedPortalServer") 'End Function #End Region #Region " Security " 'Private Shared Function AUTHENTICATION() As String ' Return "CSLA" 'System.CXXXonfiguration.ConfigurationManager.AppSettings("Authentication") 'End Function Private Shared Function GetPrincipal() As System.Security.Principal.IPrincipal 'If AUTHENTICATION() = "Windows" Then ' ' Windows integrated security ' Return Nothing 'Else ' we assume using the CSLA framework security Return System.Threading.Thread.CurrentPrincipal 'End If End Function #End Region #Region " Helper methods " 'Private Shared Function IsTransactionalMethod(ByVal Method As MethodInfo) As Boolean ' Return Attribute.IsDefined(Method, GetType(TransactionalAttribute)) ' 'Dim attrib() As Object = Method.GetCustomAttributes(GetType(TransactionalAttribute), True) ' 'Return (UBound(attrib) > -1) 'End Function Private Shared Function RunLocal(ByVal Method As MethodInfo) As Boolean Return Attribute.IsDefined(Method, GetType(RunLocalAttribute)) End Function Private Shared Function GetMethod(ByVal ObjectType As Type, ByVal method As String) As MethodInfo Return ObjectType.GetMethod(method, BindingFlags.FlattenHierarchy Or BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic) End Function Private Shared Function GetObjectType(ByVal criteria As Object) As Type If criteria.GetType.IsSubclassOf(GetType(CriteriaBase)) Then ' get the type of the actual business object ' from CriteriaBase (using the new scheme) Return CType(criteria, CriteriaBase).ObjectType Else ' get the type of the actual business object ' based on the nested class scheme in the book Return criteria.GetType.DeclaringType End If End Function Private Shared Sub Init() If Not mInitialized Then mPortalRemote = mIsRemote If mIsRemote = True AndAlso Not ChannelServices.RegisteredChannels.Length > 0 Then ' create and register our custom HTTP channel ' that uses the binary formatter Dim properties As New Hashtable() properties("name") = "HttpBinary" 'If AUTHENTICATION() = "Windows" Then ' ' make sure we pass the user's Windows credentials ' ' to the server ' properties("useDefaultCredentials") = True 'End If Dim formatter As New BinaryClientFormatterSinkProvider() Dim channel As New HttpChannel(properties, formatter, Nothing) ChannelServices.RegisterChannel(channel) '' register the data portal types as being remote 'If Len(PORTAL_SERVER) > 0 Then ' RemotingConfiguration.RegisterWellKnownClientType( _ ' GetType(Server.DataPortal), PORTAL_SERVER) 'End If 'If Len(SERVICED_PORTAL_SERVER) > 0 Then ' RemotingConfiguration.RegisterWellKnownClientType( _ ' GetType(Server.ServicedDataPortal.DataPortal), SERVICED_PORTAL_SERVER) 'End If End If End If End Sub Shared Sub New() ' see if we need to configure remoting at all 'body moved to init sub End Sub #End Region End Class