ReferenceService.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Common / AuthoringOM / Design / ReferenceService.cs / 1551714 / ReferenceService.cs

                            namespace System.Workflow.ComponentModel.Design 
{
 	using System;
	using System.Collections;
	using System.ComponentModel; 
	using System.ComponentModel.Design;
 	using System.Diagnostics; 
	using System.Reflection; 
 	using System.Globalization;
 
 	internal sealed class ReferenceService: IReferenceService, IDisposable
	{
 		private static readonly Attribute[] Attributes = new Attribute[] {BrowsableAttribute.Yes};
		private IServiceProvider provider;		// service provider we use to get to other services 
		private ArrayList addedComponents;		// list of newly added components
		private ArrayList removedComponents;	// list of newly removed components 
 		private ArrayList changedComponents;	// list of changed components, we will re-cylcle their references too	 
		private ArrayList references;			// our current list of references
 
 		internal ReferenceService(IServiceProvider provider)
 		{
			this.provider = provider;
 		} 

        ~ReferenceService() 
        { 
            Dispose(false);
        } 

		private void CreateReferences(IComponent component)
		{
			CreateReferences(string.Empty, component, component); 
 		}
 
		private void CreateReferences(string trailingName, object reference, IComponent sitedComponent) 
 		{
 			if (object.ReferenceEquals(reference, null)) 
				return;

 			this.references.Add(new ReferenceHolder(trailingName, reference, sitedComponent));
			foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(reference, Attributes)) 
			{
				object value = null; 
 				try 
				{
 					value = property.GetValue(reference); 
 				}
				catch
 				{
					// Work around!!! if an property getter throws exception then we ignore it. 
				}
				if(value != null) 
 				{ 
					BrowsableAttribute[] browsableAttrs = (BrowsableAttribute[])(value.GetType().GetCustomAttributes(typeof(BrowsableAttribute), true));
 					if(browsableAttrs.Length > 0 && browsableAttrs[0].Browsable) 
 					{
						CreateReferences(string.Format(CultureInfo.InvariantCulture, "{0}.{1}", new object[] { trailingName, property.Name }), property.GetValue(reference), sitedComponent);
 					}
				} 
			}
		} 
 
 		private void EnsureReferences()
		{ 
 			// If the references are null, create them for the first time and connect
 			// up our events to listen to changes to the container.  Otherwise, check to
			// see if the added or removed lists contain anything for us to [....] up.
 			// 
			if (this.references == null)
			{ 
				if (this.provider == null) 
 				{
					throw new ObjectDisposedException("IReferenceService"); 
 				}

 				IComponentChangeService cs = this.provider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
				Debug.Assert(cs != null, "Reference service relies on IComponentChangeService"); 
 				if (cs != null)
				{ 
					cs.ComponentAdded += new ComponentEventHandler(this.OnComponentAdded); 
					cs.ComponentRemoved += new ComponentEventHandler(this.OnComponentRemoved);
 					cs.ComponentRename += new ComponentRenameEventHandler(this.OnComponentRename); 
					cs.ComponentChanged += new ComponentChangedEventHandler(this.OnComponentChanged);
 				}

 				TypeDescriptor.Refreshed += new RefreshEventHandler(OnComponentRefreshed); 

				IContainer container = this.provider.GetService(typeof(IContainer)) as IContainer; 
 				if (container == null) 
				{
					Debug.Fail("Reference service cannot operate without IContainer"); 
					throw new InvalidOperationException();
 				}

				this.references = new ArrayList(container.Components.Count); 

 				foreach (IComponent component in container.Components) 
 				{ 
					CreateReferences(component);
 				} 
			}
			else
			{
 				if (this.addedComponents != null && this.addedComponents.Count > 0) 
				{
 					// There is a possibility that this component already exists. 
 					// If it does, just remove it first and then re-add it. 
					//
                    ArrayList clonedAddedComponents = new ArrayList(this.addedComponents); 
                    foreach (IComponent ic in clonedAddedComponents)
 					{
						RemoveReferences(ic);
						CreateReferences(ic); 
					}
 					this.addedComponents.Clear(); 
				} 

 				if (this.removedComponents != null && this.removedComponents.Count > 0) 
 				{
                    ArrayList clonedRemovedComponents = new ArrayList(this.removedComponents);
                    foreach (IComponent ic in clonedRemovedComponents)
						RemoveReferences(ic); 

 					this.removedComponents.Clear(); 
				} 
				if (this.changedComponents != null && this.changedComponents.Count > 0)
				{ 
                    ArrayList clonedChangedComponents = new ArrayList(this.changedComponents);
                    foreach (IComponent ic in clonedChangedComponents)
 					{
						RemoveReferences(ic); 
 						CreateReferences(ic);
 					} 
					this.changedComponents.Clear(); 
 				}
			} 
		}

		private void OnComponentChanged(object sender, ComponentChangedEventArgs cevent)
 		{ 
			IComponent comp = ((IReferenceService)this).GetComponent(cevent.Component);
 
 			if (comp != null) 
 			{
				if ((this.addedComponents == null || !this.addedComponents.Contains(comp)) && 
 					(this.removedComponents == null || !this.removedComponents.Contains(comp)))
				{
					if (this.changedComponents == null)
					{ 
 						this.changedComponents = new ArrayList();
						this.changedComponents.Add(comp); 
 					} 
 					else if (!this.changedComponents.Contains(comp))
					{ 
 						this.changedComponents.Add(comp);
					}
				}
			} 
 		}
 
		private void OnComponentAdded(object sender, ComponentEventArgs cevent) 
 		{
 			if (this.addedComponents == null) 
				this.addedComponents = new ArrayList();
 			this.addedComponents.Add(cevent.Component);
			if (this.removedComponents != null)
				this.removedComponents.Remove(cevent.Component); 
			if(this.changedComponents != null)
 				this.changedComponents.Remove(cevent.Component); 
		} 

 		private void OnComponentRemoved(object sender, ComponentEventArgs cevent) 
 		{
			if (this.removedComponents == null)
 				this.removedComponents = new ArrayList();
 
			this.removedComponents.Add(cevent.Component);
 
			if (this.addedComponents != null) 
				this.addedComponents.Remove(cevent.Component);
 			if (this.changedComponents != null) 
				this.changedComponents.Remove(cevent.Component);
 		}

 		private void OnComponentRename(object sender, ComponentRenameEventArgs cevent) 
		{
 			foreach (ReferenceHolder reference in this.references) 
			{ 
				if (object.ReferenceEquals(reference.SitedComponent, cevent.Component))
				{ 
 					reference.ResetName();
					return;
 				}
 			} 
		}
 		private void OnComponentRefreshed(RefreshEventArgs e) 
		{ 
			if(e.ComponentChanged != null)
				OnComponentChanged(this, new ComponentChangedEventArgs(e.ComponentChanged, null, null, null)); 
 		}

		private void RemoveReferences(IComponent component)
 		{ 
 			if (this.references != null)
			{ 
 				int size = this.references.Count; 
				for (int i = size - 1; i >= 0; i--)
				{ 
					if (object.ReferenceEquals(((ReferenceHolder)this.references[i]).SitedComponent, component))
 						this.references.RemoveAt(i);
				}
 			} 
 		}
		 
        public void Dispose() 
 		{
            Dispose(true); 
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing) 
        {
			if (this.references != null && this.provider != null) 
			{ 
				IComponentChangeService cs = this.provider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
 				if (cs != null) 
				{
 					cs.ComponentAdded -= new ComponentEventHandler(this.OnComponentAdded);
 					cs.ComponentRemoved -= new ComponentEventHandler(this.OnComponentRemoved);
					cs.ComponentRename -= new ComponentRenameEventHandler(this.OnComponentRename); 
 					cs.ComponentChanged -= new ComponentChangedEventHandler(this.OnComponentChanged);
				} 
 
				TypeDescriptor.Refreshed -= new RefreshEventHandler(OnComponentRefreshed);
				 
 				this.references = null;
				this.provider = null;
 			}
 		} 

		IComponent IReferenceService.GetComponent(object reference) 
 		{ 
			if (object.ReferenceEquals(reference, null))
				throw new ArgumentNullException("reference"); 

			EnsureReferences();

 			foreach (ReferenceHolder holder in this.references) 
			{
 				if (object.ReferenceEquals(holder.Reference, reference)) 
 					return holder.SitedComponent; 
			}
 			return null; 
		}
		string IReferenceService.GetName(object reference)
		{
 			if (object.ReferenceEquals(reference, null)) 
				throw new ArgumentNullException("reference");
 
 			EnsureReferences(); 

 			foreach (ReferenceHolder holder in this.references) 
			{
 				if (object.ReferenceEquals(holder.Reference, reference))
					return holder.Name;
			} 
			return null;
 		} 
		object IReferenceService.GetReference(string name) 
 		{
 			if (name == null) 
				throw new ArgumentNullException("name");

 			EnsureReferences();
 
			foreach (ReferenceHolder holder in this.references)
			{ 
				if (string.Equals(holder.Name, name, StringComparison.OrdinalIgnoreCase)) 
 					return holder.Reference;
			} 

 			return null;
 		}
 
		object[] IReferenceService.GetReferences()
 		{ 
			EnsureReferences(); 

			object[] references = new object[this.references.Count]; 
			for (int i = 0; i < references.Length; i++)
 				references[i] = ((ReferenceHolder)this.references[i]).Reference;

			return references; 
 		}
 		 
		object[] IReferenceService.GetReferences(Type baseType) 
 		{
			if (baseType == null) 
				throw new ArgumentNullException("baseType");

			EnsureReferences();
 
 			ArrayList results = new ArrayList(this.references.Count);
			foreach (ReferenceHolder holder in this.references) 
 			{ 
 				object reference = holder.Reference;
				if (baseType.IsAssignableFrom(reference.GetType())) 
 					results.Add(reference);
			}

			object[] references = new object[results.Count]; 
			results.CopyTo(references, 0);
 			return references; 
		} 

 		private sealed class ReferenceHolder 
 		{
			private string trailingName;
 			private object reference;
			private IComponent sitedComponent; 
			private string fullName;
 
			internal ReferenceHolder(string trailingName, object reference, IComponent sitedComponent) 
 			{
				this.trailingName = trailingName; 
 				this.reference = reference;
 				this.sitedComponent = sitedComponent;

				Debug.Assert(trailingName != null, "Expected a trailing name"); 
 				Debug.Assert(reference != null, "Expected a reference");
 
				#if DEBUG 

				Debug.Assert(sitedComponent != null, "Expected a sited component"); 
				if (sitedComponent != null)
 					Debug.Assert(sitedComponent.Site != null, "Sited component is not really sited: " + sitedComponent.ToString());
				if (sitedComponent != null && sitedComponent.Site != null)
 					Debug.Assert(sitedComponent.Site.Name != null, "Sited component has no name: " + sitedComponent.ToString()); 

 				#endif // DEBUG 
			} 

 			internal void ResetName() 
			{
				this.fullName = null;
			}
 
 			internal string Name
			{ 
 				get 
 				{
					if (this.fullName == null) 
 					{
						if (this.sitedComponent != null && this.sitedComponent.Site != null && this.sitedComponent.Site.Name != null)
						{
							this.fullName = string.Format(CultureInfo.InvariantCulture, "{0}{1}", new object[] { this.sitedComponent.Site.Name, this.trailingName }); 
 						}
						else 
 						{ 
 							#if DEBUG
							Debug.Assert(this.sitedComponent != null, "Expected a sited component"); 
 							if (this.sitedComponent != null)
								Debug.Assert(this.sitedComponent.Site != null, "Sited component is not really sited: " + this.sitedComponent.ToString());
							if (this.sitedComponent != null && this.sitedComponent.Site != null)
								Debug.Assert(this.sitedComponent.Site.Name != null, "Sited component has no name: " + this.sitedComponent.ToString()); 
 							#endif // DEBUG
							this.fullName = string.Empty; 
 						} 
 					}
					return this.fullName; 
 				}
			}

			internal object Reference 
			{
 				get 
				{ 
 					return this.reference;
 				} 
			}

 			internal IComponent SitedComponent
			{ 
				get
				{ 
 					return this.sitedComponent; 
				}
 			} 
 		}
	}
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
namespace System.Workflow.ComponentModel.Design 
{
 	using System;
	using System.Collections;
	using System.ComponentModel; 
	using System.ComponentModel.Design;
 	using System.Diagnostics; 
	using System.Reflection; 
 	using System.Globalization;
 
 	internal sealed class ReferenceService: IReferenceService, IDisposable
	{
 		private static readonly Attribute[] Attributes = new Attribute[] {BrowsableAttribute.Yes};
		private IServiceProvider provider;		// service provider we use to get to other services 
		private ArrayList addedComponents;		// list of newly added components
		private ArrayList removedComponents;	// list of newly removed components 
 		private ArrayList changedComponents;	// list of changed components, we will re-cylcle their references too	 
		private ArrayList references;			// our current list of references
 
 		internal ReferenceService(IServiceProvider provider)
 		{
			this.provider = provider;
 		} 

        ~ReferenceService() 
        { 
            Dispose(false);
        } 

		private void CreateReferences(IComponent component)
		{
			CreateReferences(string.Empty, component, component); 
 		}
 
		private void CreateReferences(string trailingName, object reference, IComponent sitedComponent) 
 		{
 			if (object.ReferenceEquals(reference, null)) 
				return;

 			this.references.Add(new ReferenceHolder(trailingName, reference, sitedComponent));
			foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(reference, Attributes)) 
			{
				object value = null; 
 				try 
				{
 					value = property.GetValue(reference); 
 				}
				catch
 				{
					// Work around!!! if an property getter throws exception then we ignore it. 
				}
				if(value != null) 
 				{ 
					BrowsableAttribute[] browsableAttrs = (BrowsableAttribute[])(value.GetType().GetCustomAttributes(typeof(BrowsableAttribute), true));
 					if(browsableAttrs.Length > 0 && browsableAttrs[0].Browsable) 
 					{
						CreateReferences(string.Format(CultureInfo.InvariantCulture, "{0}.{1}", new object[] { trailingName, property.Name }), property.GetValue(reference), sitedComponent);
 					}
				} 
			}
		} 
 
 		private void EnsureReferences()
		{ 
 			// If the references are null, create them for the first time and connect
 			// up our events to listen to changes to the container.  Otherwise, check to
			// see if the added or removed lists contain anything for us to [....] up.
 			// 
			if (this.references == null)
			{ 
				if (this.provider == null) 
 				{
					throw new ObjectDisposedException("IReferenceService"); 
 				}

 				IComponentChangeService cs = this.provider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
				Debug.Assert(cs != null, "Reference service relies on IComponentChangeService"); 
 				if (cs != null)
				{ 
					cs.ComponentAdded += new ComponentEventHandler(this.OnComponentAdded); 
					cs.ComponentRemoved += new ComponentEventHandler(this.OnComponentRemoved);
 					cs.ComponentRename += new ComponentRenameEventHandler(this.OnComponentRename); 
					cs.ComponentChanged += new ComponentChangedEventHandler(this.OnComponentChanged);
 				}

 				TypeDescriptor.Refreshed += new RefreshEventHandler(OnComponentRefreshed); 

				IContainer container = this.provider.GetService(typeof(IContainer)) as IContainer; 
 				if (container == null) 
				{
					Debug.Fail("Reference service cannot operate without IContainer"); 
					throw new InvalidOperationException();
 				}

				this.references = new ArrayList(container.Components.Count); 

 				foreach (IComponent component in container.Components) 
 				{ 
					CreateReferences(component);
 				} 
			}
			else
			{
 				if (this.addedComponents != null && this.addedComponents.Count > 0) 
				{
 					// There is a possibility that this component already exists. 
 					// If it does, just remove it first and then re-add it. 
					//
                    ArrayList clonedAddedComponents = new ArrayList(this.addedComponents); 
                    foreach (IComponent ic in clonedAddedComponents)
 					{
						RemoveReferences(ic);
						CreateReferences(ic); 
					}
 					this.addedComponents.Clear(); 
				} 

 				if (this.removedComponents != null && this.removedComponents.Count > 0) 
 				{
                    ArrayList clonedRemovedComponents = new ArrayList(this.removedComponents);
                    foreach (IComponent ic in clonedRemovedComponents)
						RemoveReferences(ic); 

 					this.removedComponents.Clear(); 
				} 
				if (this.changedComponents != null && this.changedComponents.Count > 0)
				{ 
                    ArrayList clonedChangedComponents = new ArrayList(this.changedComponents);
                    foreach (IComponent ic in clonedChangedComponents)
 					{
						RemoveReferences(ic); 
 						CreateReferences(ic);
 					} 
					this.changedComponents.Clear(); 
 				}
			} 
		}

		private void OnComponentChanged(object sender, ComponentChangedEventArgs cevent)
 		{ 
			IComponent comp = ((IReferenceService)this).GetComponent(cevent.Component);
 
 			if (comp != null) 
 			{
				if ((this.addedComponents == null || !this.addedComponents.Contains(comp)) && 
 					(this.removedComponents == null || !this.removedComponents.Contains(comp)))
				{
					if (this.changedComponents == null)
					{ 
 						this.changedComponents = new ArrayList();
						this.changedComponents.Add(comp); 
 					} 
 					else if (!this.changedComponents.Contains(comp))
					{ 
 						this.changedComponents.Add(comp);
					}
				}
			} 
 		}
 
		private void OnComponentAdded(object sender, ComponentEventArgs cevent) 
 		{
 			if (this.addedComponents == null) 
				this.addedComponents = new ArrayList();
 			this.addedComponents.Add(cevent.Component);
			if (this.removedComponents != null)
				this.removedComponents.Remove(cevent.Component); 
			if(this.changedComponents != null)
 				this.changedComponents.Remove(cevent.Component); 
		} 

 		private void OnComponentRemoved(object sender, ComponentEventArgs cevent) 
 		{
			if (this.removedComponents == null)
 				this.removedComponents = new ArrayList();
 
			this.removedComponents.Add(cevent.Component);
 
			if (this.addedComponents != null) 
				this.addedComponents.Remove(cevent.Component);
 			if (this.changedComponents != null) 
				this.changedComponents.Remove(cevent.Component);
 		}

 		private void OnComponentRename(object sender, ComponentRenameEventArgs cevent) 
		{
 			foreach (ReferenceHolder reference in this.references) 
			{ 
				if (object.ReferenceEquals(reference.SitedComponent, cevent.Component))
				{ 
 					reference.ResetName();
					return;
 				}
 			} 
		}
 		private void OnComponentRefreshed(RefreshEventArgs e) 
		{ 
			if(e.ComponentChanged != null)
				OnComponentChanged(this, new ComponentChangedEventArgs(e.ComponentChanged, null, null, null)); 
 		}

		private void RemoveReferences(IComponent component)
 		{ 
 			if (this.references != null)
			{ 
 				int size = this.references.Count; 
				for (int i = size - 1; i >= 0; i--)
				{ 
					if (object.ReferenceEquals(((ReferenceHolder)this.references[i]).SitedComponent, component))
 						this.references.RemoveAt(i);
				}
 			} 
 		}
		 
        public void Dispose() 
 		{
            Dispose(true); 
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing) 
        {
			if (this.references != null && this.provider != null) 
			{ 
				IComponentChangeService cs = this.provider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
 				if (cs != null) 
				{
 					cs.ComponentAdded -= new ComponentEventHandler(this.OnComponentAdded);
 					cs.ComponentRemoved -= new ComponentEventHandler(this.OnComponentRemoved);
					cs.ComponentRename -= new ComponentRenameEventHandler(this.OnComponentRename); 
 					cs.ComponentChanged -= new ComponentChangedEventHandler(this.OnComponentChanged);
				} 
 
				TypeDescriptor.Refreshed -= new RefreshEventHandler(OnComponentRefreshed);
				 
 				this.references = null;
				this.provider = null;
 			}
 		} 

		IComponent IReferenceService.GetComponent(object reference) 
 		{ 
			if (object.ReferenceEquals(reference, null))
				throw new ArgumentNullException("reference"); 

			EnsureReferences();

 			foreach (ReferenceHolder holder in this.references) 
			{
 				if (object.ReferenceEquals(holder.Reference, reference)) 
 					return holder.SitedComponent; 
			}
 			return null; 
		}
		string IReferenceService.GetName(object reference)
		{
 			if (object.ReferenceEquals(reference, null)) 
				throw new ArgumentNullException("reference");
 
 			EnsureReferences(); 

 			foreach (ReferenceHolder holder in this.references) 
			{
 				if (object.ReferenceEquals(holder.Reference, reference))
					return holder.Name;
			} 
			return null;
 		} 
		object IReferenceService.GetReference(string name) 
 		{
 			if (name == null) 
				throw new ArgumentNullException("name");

 			EnsureReferences();
 
			foreach (ReferenceHolder holder in this.references)
			{ 
				if (string.Equals(holder.Name, name, StringComparison.OrdinalIgnoreCase)) 
 					return holder.Reference;
			} 

 			return null;
 		}
 
		object[] IReferenceService.GetReferences()
 		{ 
			EnsureReferences(); 

			object[] references = new object[this.references.Count]; 
			for (int i = 0; i < references.Length; i++)
 				references[i] = ((ReferenceHolder)this.references[i]).Reference;

			return references; 
 		}
 		 
		object[] IReferenceService.GetReferences(Type baseType) 
 		{
			if (baseType == null) 
				throw new ArgumentNullException("baseType");

			EnsureReferences();
 
 			ArrayList results = new ArrayList(this.references.Count);
			foreach (ReferenceHolder holder in this.references) 
 			{ 
 				object reference = holder.Reference;
				if (baseType.IsAssignableFrom(reference.GetType())) 
 					results.Add(reference);
			}

			object[] references = new object[results.Count]; 
			results.CopyTo(references, 0);
 			return references; 
		} 

 		private sealed class ReferenceHolder 
 		{
			private string trailingName;
 			private object reference;
			private IComponent sitedComponent; 
			private string fullName;
 
			internal ReferenceHolder(string trailingName, object reference, IComponent sitedComponent) 
 			{
				this.trailingName = trailingName; 
 				this.reference = reference;
 				this.sitedComponent = sitedComponent;

				Debug.Assert(trailingName != null, "Expected a trailing name"); 
 				Debug.Assert(reference != null, "Expected a reference");
 
				#if DEBUG 

				Debug.Assert(sitedComponent != null, "Expected a sited component"); 
				if (sitedComponent != null)
 					Debug.Assert(sitedComponent.Site != null, "Sited component is not really sited: " + sitedComponent.ToString());
				if (sitedComponent != null && sitedComponent.Site != null)
 					Debug.Assert(sitedComponent.Site.Name != null, "Sited component has no name: " + sitedComponent.ToString()); 

 				#endif // DEBUG 
			} 

 			internal void ResetName() 
			{
				this.fullName = null;
			}
 
 			internal string Name
			{ 
 				get 
 				{
					if (this.fullName == null) 
 					{
						if (this.sitedComponent != null && this.sitedComponent.Site != null && this.sitedComponent.Site.Name != null)
						{
							this.fullName = string.Format(CultureInfo.InvariantCulture, "{0}{1}", new object[] { this.sitedComponent.Site.Name, this.trailingName }); 
 						}
						else 
 						{ 
 							#if DEBUG
							Debug.Assert(this.sitedComponent != null, "Expected a sited component"); 
 							if (this.sitedComponent != null)
								Debug.Assert(this.sitedComponent.Site != null, "Sited component is not really sited: " + this.sitedComponent.ToString());
							if (this.sitedComponent != null && this.sitedComponent.Site != null)
								Debug.Assert(this.sitedComponent.Site.Name != null, "Sited component has no name: " + this.sitedComponent.ToString()); 
 							#endif // DEBUG
							this.fullName = string.Empty; 
 						} 
 					}
					return this.fullName; 
 				}
			}

			internal object Reference 
			{
 				get 
				{ 
 					return this.reference;
 				} 
			}

 			internal IComponent SitedComponent
			{ 
				get
				{ 
 					return this.sitedComponent; 
				}
 			} 
 		}
	}
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK