VB.NET • Create A Factory Within a Factory.

Listing 1. This custom StreamFactory class wraps System.Net.WebRequest’s factory within another factory to add functionality seamlessly. Adopting this approach enables you to avoid violating one of the cardinal rules of the Abstract Factory design pattern; namely, you should treat all concrete objects as equal.

Imports System
Imports System.Xml
Imports System.IO
Imports System.Security.Cryptography
Imports System.Windows
Imports System.Windows.Forms

Public Class StreamFactory

Public Shared Function Create( _
	ByVal forUri As Uri) _
	As Stream

	Return CreateNormal(forUri, Nothing)

End Function

Public Shared Function Create( _
	ByVal forUri As Uri, _
	ByVal alternateCredentials _
	As NetworkCredential) _
	As Stream

	If forUri.Scheme = Uri.UriSchemeFile _
	And alternateCredentials IsNot Nothing Then
		Return CreateSpecial( _
			forUri, _
			alternateCredentials)
	Else
		Return CreateNormal( _
			forUri, _
			alternateCredentials)
	End If

End Function

Private Shared Function CreateNormal( _
	ByVal forUri As Uri, _
	ByVal alternateCredentials _
	As NetworkCredential) _
	As Stream

	Dim ReturnValue As Stream
	Dim Request As WebRequest
	Dim Response As WebResponse

	Request = WebRequest.Create(forUri)
	If alternateCredentials IsNot Nothing Then
		Request.Credentials = alternateCredentials
		Request.UseDefaultCredentials = False
	End If
	Response = Request.GetResponse
	ReturnValue = Response.GetResponseStream
	Return ReturnValue

End Function

Private Shared Function CreateSpecial( _
	ByVal forUri As Uri, _
	ByVal alternateCredentials _
	As NetworkCredential) _
	As Stream

	Dim LogonToken As IntPtr

	Try
		If LogonUser( _
			alternateCredentials.UserName, _
			alternateCredentials.Domain, _
			alternateCredentials.Password, _
			LOGON32_LOGON_INTERACTIVE, _
			LOGON32_PROVIDER_DEFAULT, _
			LogonToken) Then 
			Using WindowsIdentity.Impersonate( _
			LogonToken)
				Return CreateNormal( _
				forUri, Nothing)
			End Using
		Else
			Throw New SecurityException( _
				"Logon failed.")
		End If
	Finally
		If LogonToken <> IntPtr.Zero Then
			WinAPI.CloseHandle(LogonToken)
		End If
	End Try

End Function

<DllImport("kernel32")> _
	Private Shared Sub CloseHandle( _
	ByVal Handle As IntPtr)
End Sub

<DllImport("advapi32.dll", _
EntryPoint:="LogonUserW", _ 
CharSet:=CharSet.Unicode)> _
	Private Shared Function LogonUser _
	( _
	ByVal UserName As String, _
	ByVal Domain As String, _
	ByVal Password As String, _
	ByVal Type As UInt32, _
	ByVal Provider As UInt32, _
	<Out()> ByRef LogonToken As IntPtr _
	) _
	As Boolean

End Function

Private Const LOGON32_LOGON_INTERACTIVE _
	As UInt32 = 2

Private Const LOGON32_PROVIDER_DEFAULT _
	As UInt32 = 0

End Class