The FileSwapper application uses two classes that consist of shared members: Global and App. These classes act like global modules and are available from any location in the FileSwapper code. That means that you don't need to create an instance of these classes—instead, their properties and methods are always available and you can access them through the class name.
The Global class stores data that's required by multiple objects in the application. As with any application, it's always best to keep the amount of global data to a minimum. A large number of global variables usually indicates a poor structure that really isn't object-oriented. All the data in the Global class is held using public shared variables, making it widely available. For example, any code in the application can use the Global.Identity property to access information about the current computer's IP address and port number settings.
Here's the full code for the Global class:
Public Class Global ' Contains information about the current peer. Public Shared LoggedIn As Boolean = False Public Shared Identity As New Peer() ' Lists files that are available for other peers. Public Shared SharedFiles() As SharedFile ' Provides access to configuration settings that are stored in the registry. Public Shared Settings As New RegistrySettings() End Class
Though these variables are always available, some of them still need to be set at startup before they contain any useful information. For example, the Identity, SharedFiles, and Settings variables all begin in a default, empty state.
The App class also relies on shared variables to store a common set of information. It actually stores references to three separate objects, each of which will be executed on an independent thread. Using the App class, your startup code can easily initialize the threads on startup and abort them when the application is about to end. The App class also includes a private shared variable that references the web-service proxy. This ensures that no other part of the application can access the discovery service directly—instead, the application must call one of the App class methods.
Here's the outline for the App class, with all its public and private member variables:
Public Class App ' Holds a reference to the web-service proxy. Private Shared Discovery As New DiscoveryService() Public Shared SearchThread As Search Public Shared DownwnloadThread As FileDownloadQueue Public Shared UploadThread As FileServer ' (Code omitted.) End Class
The App class also defines five higher-level methods that deal with registration. First, the App.Login() method retrieves the IP address of the current computer, configures the Global.Identity property accordingly, and logs in to the discovery web service.
Public Shared Sub Login() Global.Identity.Guid = Guid.NewGuid Global.Identity.IP = _ Dns.GetHostByName(Dns.GetHostName).AddressList(0).ToString() Global.LoggedIn = Discovery.Register(Global.Identity) End Sub
The App.Logout() method uses the Global.Identity information to unregister the peer, provided the peer is currently logged in. Similarly, the App.Refresh Login() method resubmits the Global.Identity information to prevent the peer from expiring from the discovery service.
Public Shared Sub Logout() If Global.LoggedIn Then Discovery.Unregister(Global.Identity) End Sub Public Shared Sub RefreshLogin() If Global.LoggedIn Then Discovery.RefreshRegistration(Global.Identity) End If End Sub
The App.PublishFiles() method (shown next) examines files in the local share path and creates a catalog, which it assigns to the Global.SharedFiles variable. The PublishFiles() method retrieves the share path from the directory specified in the registry and examines the file extension to determine the type of file. Depending on the application settings, non-MP3 files may be ignored. Temporary files (files with the extension .tmp) are always ignored because they most likely correspond to an in-progress download. Here's the code for the PublishFiles() method:
Public Shared Function PublishFiles() As Boolean Try Dim Dir As New DirectoryInfo(Global.Settings.SharePath) Dim Files() As FileInfo = Dir.GetFiles() Dim FileList As New ArrayList() Dim File As FileInfo Dim IsMP3 As Boolean For Each File In Files IsMP3 = Path.GetExtension(File.Name).ToLower() = ".mp3" If Path.GetExtension(File.Name).ToLower() = ".tmp" Then ' Ignore all temporary files. ElseIf (Not IsMP3) And Global.Settings.ShareMP3Only Then ' Ignore non-MP3 files depending on setting. Else Dim SharedFile As New SharedFile() SharedFile.Guid = Guid.NewGuid() SharedFile.FileName = File.Name SharedFile.FileCreated = File.CreationTime If IsMP3 Then SharedFile.Keywords = MP3Util.GetMP3Keywords(File.FullName) Else ' Determine some other way to set keywords, ' perhaps by file name or file ' type. ' The default (no keywords) will prevent the ' file from appearing in a search. End If FileList.Add(SharedFile) End If Next Global.SharedFiles = CType(FileList.ToArray(GetType(SharedFile)), _ SharedFile()) Return Discovery.PublishFiles(Global.SharedFiles, Global.Identity) Catch Err As Exception MessageBox.Show(Err.ToString()) End Try End Function
If you're using non-MP3 files, you'll need to add code to determine a set of valid keywords. This code might parse the file name or look for data inside the file. In the case of MP3 files, the code retrieves the tag data using the utility methods shown in the next section.
Finally, the App.SearchForFile() method simply wraps the web method of the same name:
Public Shared Function SearchForFile(ByVal keywords() As String) As SharedFile() Return Discovery.SearchForFile(keywords) End Function