Introduction
While I was doing some major updates on a project I was doing for a client, I was also thinking about how to optimize the code; not just by using MVP pattern, but also by optimizing the way values were passwed between projects. Some of my class libraries were using the same type of properties and then they get updated in the main form. I noticed, though, that setting the same value into multiple objects with one type of property is pretty hard and unmanageable and also produces lots of lines of code. So I experimented a little bit and made a proof of concept on how to pass values into multiple projects with minimal coding, and also using Interface.
Background
Please take a look at the sample animation below. Here was have a satellite that moves in the form and there are three child forms. Those three child forms are the other three projects which are PlanetEarth, PlanetMars, and the PlanetSaturn project. The big form is our Main project. You'll notice that the three forms are getting updated every time the satellite makes its next move.
One thing about using an Interface is that you can share its values to whoever uses it. Like what I did on a simple P.O.S. project. Those three forms, PlanetEarth, PlanetMars, and PlanetSaturn are 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
The GlobalInterface
class library project which contains the Interface code (which has a NextPosition
property signature) which we're going to use later on in the Main Project.
public interface iSatellite
{
Point NextPosition { get; set; }
}
Then we have three projects which have the same code (for demo only) which use 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)
{
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 the 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 the 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()
{
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();
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);
}
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);
}
public Point NextPosition { get; set; }
}
As you can see on the code below, we implemented the iSatellite interface with the 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 three seconds and you can see we update the "NextPosition
" X and Y values. The three projects that are bound in the interface are automatically updated.
So what are the benefits 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 project PlanetEarth, PlanetMars, and PlanetSaturn are using the 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 three 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.
Please feel free to play with the sample project at the top of the page.