65.9K
CodeProject 正在变化。 阅读更多。
Home

使用接口在多个项目之间传递值

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (5投票s)

2012年9月4日

CPOL

3分钟阅读

viewsIcon

39553

downloadIcon

1026

使用接口在多个项目之间传递值

引言

当我在为一个客户进行一个项目的重大更新时,我也在思考如何优化代码;不仅通过使用 MVP 模式,还通过优化在项目之间传递值的方式。我的一些类库正在使用相同类型的属性,然后在主窗体中进行更新。但我注意到,将相同的值设置到具有一种属性类型的多个对象中非常困难且难以管理,并且还会产生大量的代码行。所以我做了一些实验,并制作了一个概念验证,展示了如何以最少的编码将值传递到多个项目中,并且还使用了接口。

背景

请看下面的示例动画。这里我们有一个在窗体中移动的卫星,并且有三个子窗体。这三个子窗体是另外三个项目,分别是 PlanetEarth、PlanetMars 和 PlanetSaturn 项目。大的窗体是我们的 Main 项目。您会注意到,每次卫星移动到下一个位置时,这三个窗体都会被更新。

使用接口的一个好处是,您可以将其值共享给任何使用它的人。就像我在一个简单的 P.O.S. 项目中所做的那样。这三个窗体,PlanetEarth、PlanetMars 和 PlanetSaturn,都在使用一个接口,但它们都获得了更新。

那么,为什么要使用接口而不是为每个项目创建一个属性呢?

因为就像我说的,你可以将这些值在多个项目之间共享,或者共享给任何使用它的人。 

让我们进入代码 

GlobalInterface 类库项目包含接口代码(具有 NextPosition 属性签名),我们稍后将在 Main 项目中使用它。

public interface iSatellite
{
	Point NextPosition { get; set; }
}

然后我们有三个项目,它们具有相同的代码(仅用于演示),这些项目使用此 iSatellite 接口。它们是 PlanetEarth、PlanetMars 和 PlanetSaturn。让我们以 PlanetEarth 为例。

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();
}

正如您所注意到的,我们使用 Timer 对象来显示卫星的下一个位置。我们也可以使用 Event 来声明卫星正在进行下一步移动。

InitializeSatellite(GlobalInterface.iSatellite satellite) 将在我们的 Main 项目中调用,以将 "this.Satellite" 绑定到我们的 Main 项目。 

接下来是我们的 Main 项目,它实现了 iSatellite 接口。

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; }
}

正如您在下面的代码中看到的,我们使用 NextPosition 属性(具有 Point 类型)实现了 iSatellite 接口,我们将使用它来更新卫星的位置。在 timer1_Tick 事件中,每三秒钟触发一次,您可以看到我们更新了 "NextPosition" 的 X 和 Y 值。绑定到该接口的三个项目会自动更新。

那么,在这种在多个 visual studio 项目之间传递值的类型的问题中,使用接口有什么好处呢?

  • 更少的代码 
  • 我们不需要更新每个项目的值。 
  • 易于管理 
  • 更结构化。 

比较属性与接口的使用 

假设每个项目 PlanetEarth、PlanetMars 和 PlanetSaturn 都在使用 NextPosition 属性

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;
}

但是当我们使用接口时 

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);
}

我们只需要更新我们从 iSatellite 实现的属性,所有三个项目也会自动更新。 

希望您了解了在项目中实现接口的另一种特殊方法,不仅在 Windows Forms 中,而且在 Windows Phone、Windows 8、Silverlight 和 WPF 项目中也是如此。 

请随意使用页面顶部的示例项目。

© . All rights reserved.