Introduction
In this article you will find a very interesting note about the way that you can share any kind of Windows control functionality from the server application to the client application.
Note
For simplicity purpose you will find no complex code in the source code.
Background
In the past if you shared a class with the .NET Remoting you would certainly know these notes:
- You can't use a static member in the shared class.
- You don't have access to shared class in the server application except when you share an instance with Marshal Method from
RemotingServices
class
Using the code
So, the code consists of three projects:
RemoteLib
is a class library project and is the shared library. It contains two classes:
RemotableClass
is the shared class. SharedResourcesHandler
class contains shared controls in the static property form.
RemoteServer
is a windows application project and is the hosting application for the RemoteLib
library.RemoteClient
is a windows application project and is the client application for the RemoteLib
library.
Shared Class Library
private static TextBox innerTextBox;
public static TextBox InnerTextBox
{
get { return innerTextBox; }
set { innerTextBox = value; }
}
private static MonthCalendar innerMonthCalendar;
public static MonthCalendar InnerMonthCalendar
{
get { return innerMonthCalendar; }
set { innerMonthCalendar = value; }
}
Any kind of .NET controls could be used Instead of TextBox and MonthCalendar to be shared.
In the RemotableClass
class you will use these controls to set properties.
Indeed the RemotableClass
class is a wrapper class for publishing controls functionality to the clients.
private delegate void UIThreadHandler<T>(T param);
public RemotableClass()
{
}
public override object InitializeLifetimeService()
{
ILease lease = (ILease)base.InitializeLifetimeService();
if (lease.CurrentState == LeaseState.Initial)
{
lease.InitialLeaseTime = TimeSpan.FromMinutes(10);
}
return lease;
}
public void WriteText(string text)
{
if (SharedResourcesHandler.InnerTextBox != null)
{
UIThreadHandler<string> uiThreadHandler =
new UIThreadHandler<string>(AsyncWriteText);
if (SharedResourcesHandler.InnerTextBox.InvokeRequired)
SharedResourcesHandler.InnerTextBox.BeginInvoke(uiThreadHandler,
text);
else
SharedResourcesHandler.InnerTextBox.Text = text;
}
}
private void AsyncWriteText(string text)
{
SharedResourcesHandler.InnerTextBox.Text = text;
}
public void ChangeDate(DateTime date)
{
if (SharedResourcesHandler.InnerMonthCalendar != null)
{
UIThreadHandler<DateTime> uiThreadHandler =
new UIThreadHandler<DateTime>(AsyncChangeDate);
if (SharedResourcesHandler.InnerMonthCalendar.InvokeRequired)
SharedResourcesHandler.InnerMonthCalendar.BeginInvoke(
uiThreadHandler, date);
else
SharedResourcesHandler.InnerMonthCalendar.SetDate(date);
}
}
private void AsyncChangeDate(DateTime date)
{
SharedResourcesHandler.InnerMonthCalendar.SetDate(date);
}
Changing properties of shared controls must be a cross thread call, and done with a middle generic delegate named UIThreadHandler
Server Application
So where is the control when you are filling static members of the SharedResourcesHandler
class?
The answer is one line per control in the server application like this:
SharedResourcesHandler.InnerTextBox = this.txtRemote;
SharedResourcesHandler.InnerMonthCalendar = this.mcRemote;
Remaining server code is for Registering RemotableClass for enabling remote access
TcpServerChannel channel = new TcpServerChannel(8080);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.ApplicationName = "RemotableClass";
RemotingConfiguration.RegisterWellKnownServiceType(typeof(
RemoteLib.RemotableClass), "RemotableClass",
WellKnownObjectMode.SingleCall);
Also you can use the Remoting section in the server configuration instead of preceding code.
Client Application
In the client application the first step is getting remote object with this:
TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel,false);
rClass = (RemotableClass)Activator.GetObject(typeof(RemotableClass),
"tcp://127.0.0.1:8080/RemotableClass");
I used localhost for testing purpose you can use any valid IP Addresses instead.
Also you can use configuration file to configure remoting enabled application.
Second step is calling shared object wrapper methods with events in the client application.
private void txtRemote_TextChanged(object sender, EventArgs e)
{
rClass.WriteText(txtRemote.Text);
}
private void mcRemote_DateChanged(object sender, DateRangeEventArgs e)
{
rClass.ChangeDate(mcRemote.SelectionStart);
}
This is a test application, in your real application you must use this trick object oriented.