Proxy Design Pattern in Visual Basic .NET

September 11, 2017

Definition

Provide a surrogate or placeholder for another object to control access to it.

You can understand the Proxy Design Pattern in following
You have two objects called ObjectA and ObjectB. So ObjectA needs to communicate with other ObjectB.

How are you going to do this?

You can simple make a reference to ObjectB can execute its method

But if the ObjectB does not want to ObjectA to access its all methods, you need some kind of controlling the access to the ObjectA

This kind of access controlling can be achieved with Proxy Design Pattern

Now we will have a look at the UML diagram of the Proxy Design Pattern
Proxy Design Pattern UML

Participants

The classes and objects participating in this pattern are:

Proxy
– Maintain reference to the Real Subject
– This has identical interface what you find in Real Subject
– controls access to the real subject and may be responsible for creating and deleting it.

Subject
– Define interface for Proxy and Real Subject
RealSubject
– Defines the real object that the proxy represents.

Proxy Design Pattern Example in VB.NET

In this example I am going to build application to run shell command from the VB.NET form and display the output from shell in RichTextbox control

To run the Shell command I have ShellCommand class with run() method

Public Function RunCommand(cmd As String) As String

        Dim process As New Process()
        process.StartInfo.FileName = "cmd.exe"
        process.StartInfo.UseShellExecute = False
        process.StartInfo.RedirectStandardOutput = True
        process.StartInfo.RedirectStandardInput = True
        process.StartInfo.CreateNoWindow = True
        AddHandler process.OutputDataReceived, AddressOf OutputHandler
        process.Start()
        Dim SW As System.IO.StreamWriter = process.StandardInput
        SW.WriteLine(cmd)

        SW.WriteLine("exit")
        ' Asynchronously read the standard output of the spawned process. 
        ' This raises OutputDataReceived events for each line of output.
        process.BeginOutputReadLine()
        process.WaitForExit()
        process.Close()
        Return output.ToString()

    End Function

But I do not want give permission to user to run every shell command, as you know, it is extremely dangerous. So I want control user whom can run dir, cd and mkdir only

To implement above scenario you can use Proxy Design Pattern

Following UML diagram shows the classes and interfaces for our implementation

Proxy Design Pattern Example UML

Now we will try to implement the interface and classes using VB.NET
First you need to code the interface IShellCommand which has the RunCommand with one argument to pass the shell command

IshellCommand Interface (Subject Interface)

Public Interface IShellCommand
    Function RunCommand(ByVal cmd As String) As String
End Interface

Next, You can implement the IShellCommand interface with ShellCommand concrete class. We call this class as real subject
ShellCommand Class (Real Subject)

Imports System.Text

Public Class ShellComand
    Implements IShellCommand



    Private Delegate Sub InvokeWithString(ByVal text As String)
    Dim lineCount As Integer = 0
    Dim output As StringBuilder = New StringBuilder()

    Sub OutputHandler(sender As Object, e As DataReceivedEventArgs)
        If Not String.IsNullOrEmpty(e.Data) Then
            lineCount += 1

            ' Add the text to the collected output.
            output.Append(Environment.NewLine + "[" + lineCount.ToString() + "]: " + e.Data)
        End If
    End Sub


    Public Function RunCommand(cmd As String) As String Implements IShellCommand.RunCommand
        Dim process As New Process()
        process.StartInfo.FileName = "cmd.exe"
        process.StartInfo.UseShellExecute = False
        process.StartInfo.RedirectStandardOutput = True
        process.StartInfo.RedirectStandardInput = True
        process.StartInfo.CreateNoWindow = True
        AddHandler process.OutputDataReceived, AddressOf OutputHandler
        process.Start()
        Dim SW As System.IO.StreamWriter = process.StandardInput
        SW.WriteLine(cmd)

        SW.WriteLine("exit")
        ' Asynchronously read the standard output of the spawned process. 
        ' This raises OutputDataReceived events for each line of output.
        process.BeginOutputReadLine()
        process.WaitForExit()
        process.Close()
        Return output.ToString()
    End Function
End Class

Next, You can create the ShellCommandProxy which implements the IShellCommand Interface
Inside the RunCommand method you can restrict the access to Real Subject ShellCommand

ShellCommandProxy class (Proxy)

Public Class ShellCommandProxy
    Implements IShellCommand


    Private shell As New ShellComand()

    Public Function RunCommand(cmd As String) As String Implements IShellCommand.RunCommand

        'User can only run Dir, CD .. only
        If ((cmd.ToLower() = "dir") Or (cmd.ToLower() = "cd ..")) Then
            Return shell.RunCommand(cmd)
        Else
            MessageBox.Show("You are not allowed to run this command")
        End If

        Return ""


    End Function
End Class

Client

To test this design pattern you can build simple user interface using VB.NET forms as shown in below

Proxy Design Pattern UI

You can add following code to the click event of the “Run” button

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim shellProxy As New ShellCommandProxy()
        RichTextBox1.Text = shellProxy.RunCommand(TextBox1.Text)

    End Sub

When you run the project you can execute only the dir and cd..