' ******************************************************************************
' **
' ** Yahoo Finance Managed
' ** Written by Marius Häusler 2010
' ** It would be pleasant, if you contact me when you are using this code.
' ** Contact: YahooFinanceManaged@gmail.com
' ** Project Home: http://code.google.com/p/yahoo-finance-managed/
' **
' ******************************************************************************
' **
' ** Copyright 2010 Marius Häusler
' **
' ** Licensed under the Apache License, Version 2.0 (the "License");
' ** you may not use this file except in compliance with the License.
' ** You may obtain a copy of the License at
' **
' ** http://www.apache.org/licenses/LICENSE-2.0
' **
' ** Unless required by applicable law or agreed to in writing, software
' ** distributed under the License is distributed on an "AS IS" BASIS,
' ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
' ** See the License for the specific language governing permissions and
' ** limitations under the License.
' **
' ******************************************************************************
Namespace Base
''' <summary>
''' Provides methods and properties for downloading data and controlling these download processes. This class must be inherited.
''' </summary>
''' <remarks>This class can not be instanced without inheritation</remarks>
Public MustInherit Class Download
Protected Event AsyncStreamDownloadCompleted(ByVal sender As Download, ByVal e As StreamDownloadCompletedEventArgs)
Friend ReadOnly mHelper As New MyHelper
Private ReadOnly mWebClients As New List(Of TimeoutWebClient)
Private mProxy As IWebProxy = WebProxy.GetDefaultProxy
Private mTimeout As Integer = 30000
Private mGui As New System.Windows.Forms.Control
''' <summary>
''' Gets the user arguments of each download process.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks>If you just need a single object, you should use UserArgs(Int32) property, because of higher performance.</remarks>
Public ReadOnly Property UserArgs() As Object()
Get
If mWebClients.Count > 0 Then
Dim lst(mWebClients.Count - 1) As Object
For i As Integer = 0 To mWebClients.Count - 1
Dim ea As DownloadEventArgs = TryCast(mWebClients(i).UserArgs, DownloadEventArgs)
If ea IsNot Nothing Then
lst(i) = ea.UserArgs
Else
lst(i) = mWebClients(i).UserArgs
End If
Next
Return lst
Else
Return New Object() {}
End If
End Get
End Property
''' <summary>
''' Gets the user argument of a download process at a specific index position.
''' </summary>
''' <param name="index">The index position of the download</param>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property UserArgs(ByVal index As Integer) As Object
Get
If index < 0 Or index > mWebClients.Count - 1 Then
Throw New IndexOutOfRangeException("The index is out of download list range.")
Else
Return Me.GetDeeperObject(mWebClients(index).UserArgs)
End If
End Get
End Property
''' <summary>
''' Gets or sets the time in miliseconds when the download will cancel if the time reached before it is completed.
''' </summary>
''' <value>Timeout in miliseconds. If value is '-1', the next download wont have a timeout.</value>
''' <returns>The timeout in miliseconds.</returns>
''' <remarks></remarks>
Public Property Timeout() As Integer
Get
Return mTimeout
End Get
Set(ByVal value As Integer)
If value >= 0 Then : mTimeout = value
Else : mTimeout = 0
End If
End Set
End Property
''' <summary>
''' Gets or sets the used proxy setting for download.
''' </summary>
''' <value></value>
''' <returns>The actual setted proxy</returns>
''' <remarks>Default value are proxy settings from Internet Explorer/Windows Internet Settings.</remarks>
Public Property Proxy() As IWebProxy
Get
Return mProxy
End Get
Set(ByVal value As IWebProxy)
mProxy = value
End Set
End Property
''' <summary>
''' Gets the number of actually running asynchronous downloads.
''' </summary>
''' <value></value>
''' <returns>The number of active downloads</returns>
''' <remarks></remarks>
Public ReadOnly Property AsyncDownloadsCount() As Integer
Get
Return mWebClients.Count
End Get
End Property
Protected Sub New()
mGui.CreateControl()
End Sub
Protected Function DownloadStream(ByVal url As String) As StreamResponse
Using wc As New TimeoutWebClient(mGui, mTimeout)
If mProxy IsNot Nothing Then wc.Proxy = mProxy
Return wc.Download(url)
End Using
End Function
Protected Sub DownloadStreamAsync(ByVal url As String, ByVal args As Object)
Dim wc As New TimeoutWebClient(mGui, mTimeout)
If mProxy IsNot Nothing Then wc.Proxy = mProxy
AddHandler wc.AsyncDownloadCompleted, AddressOf Me.AsyncDownload_Completed
mWebClients.Add(wc)
wc.DownloadAsync(url, args)
End Sub
''' <summary>
''' Cancels all running downloads.
''' </summary>
''' <returns>TRUE, if all downloads were canceled. FALSE, if something goes wrong.</returns>
''' <remarks></remarks>
Public Function CancelAsyncAll() As Boolean
If mWebClients.Count > 0 Then
For i As Integer = mWebClients.Count - 1 To 0 Step -1
mWebClients(i).CancelAsync()
Next
End If
Return mWebClients.Count = 0
End Function
''' <summary>
''' Cancels all running downloads containing the passed user argument.
''' </summary>
''' <param name="userArgs">The user argument that the download object contains.</param>
''' <returns>The number of canceled downloads.</returns>
''' <remarks></remarks>
Public Function CancelAsync(ByVal userArgs As Object) As Integer
If mWebClients.Count > 0 Then
Dim count As Integer = 0
For i As Integer = mWebClients.Count To 0 Step -1
If Me.DeepUserArgsEqual(mWebClients(i).UserArgs, userArgs) Then
mWebClients(i).CancelAsync()
count += 1
End If
Next
Return count
Else
Return 0
End If
End Function
''' <summary>
''' Cancels a running download at specific index position.
''' </summary>
''' <param name="index">The index position of the download process in queue.</param>
''' <remarks></remarks>
Public Sub CancelAsyncAt(ByVal index As Integer)
mWebClients(index).CancelAsync()
End Sub
''' <summary>
''' Proves if the download processes contains the passed user argument.
''' </summary>
''' <param name="userArgs">Individual user argument that the download contains.</param>
''' <returns>The number of download processes containing the passed user argument.</returns>
''' <remarks></remarks>
Public Function Contains(ByVal userArgs As Object) As Integer
Dim count As Integer = 0
For Each wc As TimeoutWebClient In mWebClients
If Me.DeepUserArgsEqual(wc.UserArgs, userArgs) Then count += 1
Next
Return count
End Function
Private Sub AsyncDownload_Completed(ByVal sender As TimeoutWebClient, ByVal ea As StreamDownloadCompletedEventArgs)
RemoveHandler sender.AsyncDownloadCompleted, AddressOf AsyncDownload_Completed
If mWebClients.Contains(sender) Then mWebClients.Remove(sender)
RaiseEvent AsyncStreamDownloadCompleted(Me, ea)
sender.Dispose()
End Sub
Private Function DeepUserArgsEqual(ByVal argsX As Object, ByVal argsY As Object) As Boolean
Return Me.GetDeeperObject(argsX) Is Me.GetDeeperObject(argsY)
End Function
Private Function GetDeeperObject(ByVal args As Object) As Object
Dim deeperObj As Object = Nothing
If args IsNot Nothing AndAlso TypeOf args Is DownloadEventArgs Then : deeperObj = DirectCast(args, DownloadEventArgs).UserArgs
Else : deeperObj = args
End If
If deeperObj IsNot Nothing AndAlso TypeOf deeperObj Is DownloadEventArgs Then deeperObj = Me.GetDeeperObject(deeperObj)
Return deeperObj
End Function
End Class
Public Class StreamDownloadCompletedEventArgs
Inherits DownloadCompletedEventArgs
Public Overloads ReadOnly Property Response() As StreamResponse
Get
Return DirectCast(MyBase.Response, StreamResponse)
End Get
End Property
Friend Sub New(ByVal userArgs As Object, ByVal response As StreamResponse)
MyBase.New(userArgs, response)
End Sub
End Class
Public Class StreamResponse
Inherits Response
Public Overloads ReadOnly Property Result() As IO.MemoryStream
Get
Return DirectCast(MyBase.Result, IO.MemoryStream)
End Get
End Property
Friend Sub New(ByVal info As ConnectionInfo, ByVal result As IO.MemoryStream)
MyBase.New(info, result)
End Sub
End Class
End Namespace