Earlier when I was doing some major update on a project I was working on for a client, I was also thinking how to optimize the code, not just by using MVP pattern and also the way of passing values between projects. Some of my class libraries where using the same type of property and then gets updated in the main form. I noticed though that setting the same value into the multiple objects with one type of property is pretty hard and unmanageable and also producing a lot of lines of codes. So I experimented a little bit and made an proof on concept how to pass values into multiple projects with minimal coding and using Interface.
Let's see the sample animation below. What was shown there is we have satellite that moves in the form and there are 3 child forms. Those 3 child forms are the other 3 projects which are PlanetEarth, PlanetMars, and PlanetSaturn project and the big the form is our Main project. You'll notice that the 3 forms are getting updated everytime the satellite make its next move.

What is so interesting in using an Interface is you can share its values to whoever uses it. Like what I did on that simple P.O.S. project. Those 3 forms, PlanetEarth, PlanetMars, and PlanetSaturn is using one interface but they all get the update.
So why Interface instead of making a property for each project?
Because like I said, you can share the values between multiple projects or whoever uses it.
Let's get into the code
In this sample VS solution. We have 5 projects.
GlobalInterface class library project which contains the Interface code which have an NextPosition property signature what we're going to use later on the Main Project
public interface iSatellite
{
Point NextPosition { get; set; }
}
Then we have 3 projects that has the same code (For demo only) which is using this iSatellite interface. These are the PlanetEarth, PlanetMars, and PlanetSaturn. Let's take PlanetEarth for example
GlobalInterface.iSatellite Satellite;
public Form1()
{
InitializeComponent();
timer1.Interval = 100;
timer1.Tick += new EventHandler(timer1_Tick);
}
void timer1_Tick(object sender, EventArgs e)
{
// update the location information of the satellite
label2.Text = string.Format("X: {0}\r\nY:{1}", this.Satellite.NextPosition.X, this.Satellite.NextPosition.Y);
}
public void InitializeSatellite(GlobalInterface.iSatellite satellite)
{
this.Satellite = satellite;
this.timer1.Start();
}
As you noticed, we used Timer object to show the next location of the satellite. We could also use Event to shout that the satellite is making a next move.
InitializeSatellite(GlobalInterface.iSatellite satellite) will be called on our Main Project to bind the "this.Satellite" into our Main project.
Next is our Main project that implements iSatellite interface
public partial class MainController : Form, GlobalInterface.iSatellite
{
TweenLibrary tween;
Random destXY = new Random(DateTime.Now.Millisecond);
List<Form> forms;
public MainController()
{
InitializeComponent();
InitializeControls();
InitializeControlEvents();
}
public void InitializeControls()
{
// show our 3 forms
PlanetEarth.Form1 earth = new PlanetEarth.Form1();
earth.InitializeSatellite(this);
earth.Show();
PlanetMars.Form1 mars = new PlanetMars.Form1();
mars.InitializeSatellite(this);
mars.Show();
PlanetSaturn.Form1 saturn = new PlanetSaturn.Form1();
saturn.InitializeSatellite(this);
saturn.Show();
// then put them on the list to update their location
forms = new List<Form>()
{
earth, mars, saturn
};
tween = new TweenLibrary();
timer1.Interval = Convert.ToInt32(TimeSpan.FromSeconds(3).TotalMilliseconds);
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Start();
}
public void InitializeControlEvents()
{
this.LocationChanged += new EventHandler(Form1_LocationChanged);
}
/// <summary>
/// update child form positions
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void Form1_LocationChanged(object sender, EventArgs e)
{
int last_y = this.Location.Y;
foreach (Form frm in forms)
{
frm.Location = new Point(this.Location.X + this.Size.Width, last_y);
last_y = frm.Location.Y + frm.Size.Height;
}
}
void timer1_Tick(object sender, EventArgs e)
{
this.NextPosition = new Point()
{
X = destXY.Next(this.ClientSize.Width),
Y = destXY.Next(this.ClientSize.Height)
};
tween.startTweenEvent(picSatellite, this.NextPosition.X, this.NextPosition.Y, "easeinoutcubic", 100);
}
/// <summary>
/// Implement GlobalInterface.iSatellite property
/// </summary>
public Point NextPosition { get; set; }
}
As you can see just below on that code, we implemented iSatellite interface with NextPosition property with a Point type which we're going to use to update the location of the satellite. In the timer1_Tick event, this gets triggered every 3 seconds and you can see, we update the "NextPosition" X and Y values. The 3 projects that is bound in the interface are automatically updated.
So what is the benefit of the Interface in this type of problem about passing values between multiple visual studio projects?
- Lesser code
- We do not need to update the values for each project.
- Easy to manage
- More structured.
Comparing the usage of Property vs Interface
Let's say each projects PlanetEarth, PlanetMars, and PlanetSaturn are using NextPosition Property
void timer1_Tick(object sender, EventArgs e)
{
Point newXY = new Point()
{
X = destXY.Next(this.ClientSize.Width),
Y = destXY.Next(this.ClientSize.Height)
};
this.earth.NextPosition = newXy;
this.mars.NextPosition = newXy;
this.saturn.NextPosition = newXy;
}
But when we use Interface
void timer1_Tick(object sender, EventArgs e)
{
this.NextPosition = new Point()
{
X = destXY.Next(this.ClientSize.Width),
Y = destXY.Next(this.ClientSize.Height)
};
tween.startTweenEvent(picSatellite, this.NextPosition.X, this.NextPosition.Y, "easeinoutcubic", 100);
}
We only update the property we implemented from iSatellite and all 3 projects are automatically updated as well.
Hope you learned about another special way of implementing Interface in your projects, not only in Windows Forms, but in Windows Phone, Windows 8, Silverlight, and WPF projects as well.
Here's the a sample project that you can play with.