.Net Techniques


Google

.Net Random Number Generator

Random class in .Net is part of System namespace
Declare an object
System.Random randomNumberGenerator = new System.Random();
random.NextDouble() to get the next random number between 0.0 and 1.0;
random.Next() to get the nexy random integer between 
Byte[] b = new Byte[10];
random.NextBytes(b); to set an array of bytes
To set a seed for the random number generator
int seed = 137;
System.Random randomNumberGenerator = new System.Random(seed);

Static Constructors

Cannot declare with an access modifier (ie no public, private, etc)
Cannot have any parameters
Cannot be invoked

Example of a class with a Static constructor
	public class HighPerfTimer
	{
		private static long s_Freq = 0;
	
		/// 
		/// Static Constructor
		/// 
		static HighPerfTimer()
		{
			Win32.Api.QueryPerformanceFrequency(out s_Freq);
		}

		/// 
		/// Get Some Point In Time
		/// 
		public static double TimePoint
		{
			get
			{
				if (s_Freq == 0)
					throw new Exception("High-performance counters not supported");

				long time = 0;
				Win32.Api.QueryPerformanceCounter(out time);
				return (double)time/s_Freq;
			}
		}
	}

Object Properties In Visual Studio Variables Window

Properties in Visual Studio debugger. By default, visual studio debugger displays object Properties in the variables window. This can be dangerous as the property evaluation can change the state of your object In the 'Options' dialog under 'Debugging' is a check box 'Allow property evaluation in variables windows'. I recommend switching this off otherwise Visual studio could modify the state of your objects just trying to display properties of an object. Could this also effect the speed of visual studio?

Threads And Thread Synchronisation

See MSDN article for an insight into .Net thread synchronistaion primatives 'lock' and 'Monitor'
Note that 
lock(accessorObject)
{
     // Access the object
     ...        
}
is the same as
Monitor.Enter(accessorObject);
try 
{
     // Access the object
     ...        
}
finally {
    Monitor.Exit(accessorObject); // Unlock the object
}
The article explains why never to lock on the this pointer (its a security risk) but to always use a private object created just for the task. Monitor is more than just a critical Section type structure it has a call to block a thread (Wait) until another call releases it (Pulse, PulseAll). If you wake a thread up from another Fred using a Pulse or PulseAll you can yield control to it with the following line. Thread.Sleep(0); An alternative to the Monitor.Wait/Monitor.Pulse combination is to use Events Use AutoResetEvent threadEvent = new AutoResetEvent(); ... threadEvent.WaitOne() // Thread is blocked at this point until the thread event is signalled ... In another thread threadEvent.Set() // Set the the thread event and allow the other thread to continue Handling calls from other Threads in GUI Thread In Win32 it was necessary to PostMessage to the GUI thread from the worker thread There was a special method call for this 'PostThreadMessage()' or something. .Net has a better idea. On the Form class there is a 'Invoke' method. A worker thread will call this Invoke passing a delegate and some other data parameters. In its own time the GUI will invoke the delegate on its own thread. This is a step up from Win32 where you jast pas a piece of data to the GUI. Now you can pass a pointer to a function for it to execute. Now have learned that it is better to use BeginInvoke(). Although Invoke will is asynchronous relative to the GUI thread, the calling thread will be blocked until the GUI thread has invoked the delegate passed in the BeginInvoke. There is some argument as to whether a EndInvoke is required after a BeginInvoke haas been used. Found a couple of sites offering an AsyncHelper that automatically calls the EndInvoke. Also found that the InvokeRequired can be called to check if current thread about to call a delegate on a form is the GUI thread. If it isnt then the method returns false and the BeginInvoke/Invoke should be used to call the method instead. // setup code object.RemoteUpdate += new UpdateHandler(RemoteUpdateFunc); public void RemoteUpdateFunc(object sender, RemoteUpdateEventArgs args) { if (InvokeRequired) AsyncHelper.FireAndForget(sd, "pi", 3.1415927);(new UpdateHandler(RemoteUpdateFunc), new object[] {sender, args}); else { RemoteUpdateFunc(...); } } To get the current thread ID, use this int tid = AppDomain.GetCurrentThreadId(); I generally set the Name property of the thread to be this ID. This helps with debugging as the Thread.Name can be included in any tracing. Have found when using threads in .NET that the age old problem of thread management still exists. What does thread management entail, ensuring that created threads finish and that those that dont are destroyed and that all this happens before the main process finishes. // AsyncHelper // // This class provides a FireAndForget method that facilitates // calling an arbitrary method asynchronously w/o worrying about // or waiting for the return value. // // The usage model is along these lines (example assumes // the existence of void SomeMethod(string, double). // // SomeDelegate sd = new SomeDelegate(SomeMethod); // AsyncHelper.FireAndForget(sd, "pi", 3.1415927); // // Note - there's an extra (IMO) level of indirection in the // following code that I don't think should be necessary. The // goal is to call Delegate.DynamicInvoke using BeginInvoke. // Using BeginInvoke gets us asynchrony, using DynamicInvoke // makes this generically reusable for any delegate. However, // when I call DynamicInvoke directly I get an undetailed // execution engine fatal error. When I use BeginInvoke to // call a shim method that just turns around and calls // DynamicInvoke, things work. Strange (and consistent on // the 1.0 and 1.1 runtimes). // public class AsyncHelper { delegate void DynamicInvokeShimProc( Delegate d, object[] args ); static DynamicInvokeShimProc dynamicInvokeShim = new DynamicInvokeShimProc(DynamicInvokeShim); static AsyncCallback dynamicInvokeDone = new AsyncCallback(DynamicInvokeDone); public static void FireAndForget( Delegate d, params object[] args ) { dynamicInvokeShim.BeginInvoke(d, args, dynamicInvokeDone, null); } static void DynamicInvokeShim( Delegate d, object[] args ) { d.DynamicInvoke(args); } static void DynamicInvokeDone( IAsyncResult ar ) { dynamicInvokeShim.EndInvoke(ar); } } Test if a Thread is running using: bool threadRunning = (myThread.ThreadState & (ThreadState.Stopped | ThreadState.Unstarted)) == 0);

String to and from an Enum


This example uses an ComboBox to store the enumeration values as strings

To convert an enum to a string use:
MyComboBox.SelectedItem = m_Musica1Info.GradationCurve.ToString();

The reverse process is a little more complicated
GradationCurve gc = (GradationCurve) Enum.Parse(typeof(GradationCurve), MyComboBox.SelectedItem.ToString(), true);

Colors in .NET

		
To create a color with a given RGB value use
Color color = Color.FromRGB(0xf1, 0xee, ox45);

HTML Trick to Copy to the Clipboard

            

C# Class Generator - Found this little trick here

Inside <form> block place the following article <textarea name="tbCutPaste" rows="3" cols="120" id="tbCutPaste"></textarea> <br/> <input type="button" onclick="javascript:HighlightAll('Form1.tbCutPaste');" value="Copy To Clipboard" />

Path Methods




When
  string pathroot  = Path.GetPathRoot(filename); 
  string filename  = Path.GetFileName(filename); 
  string directory = Path.GetDirectoryName(filename); 
  string fullpath  = Path.GetFullPath(filename); 
  string fileNoExt = Path.GetFileNameWithoutExtension(filename);


and filename == @"Z:\ADC_QS_NGA\DataFiles\OriginalPixelFiles\FBK00006_2048x2512x12.raw"
pathroot  == @"Z:\"; 
filename  == @"FBK00006_2048x2512x12.raw"; 
directory == @"Z:\ADC_QS_NGA\DataFiles\OriginalPixelFiles"; 
fullpath  == @"Z:\ADC_QS_NGA\DataFiles\OriginalPixelFiles\FBK00006_2048x2512x12.raw"; 
fileNoExt == @"FBK00006_2048x2512x12";

then
	string newFilename = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename)) + ".mmf";
produces
newFilename == @"Z:\ADC_QS_NGA\DataFiles\OriginalPixelFiles\FBK00006_2048x2512x12.mmf"

Path.Combine Test

		

Here is some article to Test 'Path.Combine'. Its from the MSDN web page (only they dont show the results of the test). I also added some of my own tests

private void TestPathCombine() { string path1 = "c:\\temp"; string path2 = "subdir\\file.txt"; string path3 = "c:\\temp.txt"; string path4 = "c:^*&)(_=@#'\^&#2.*(.txt"; string path5 = ""; string path6 = null; string path7 = @"c:/temp/xxx.abc"; string path8 = @"filename.txt"; CombinePaths(path1, path2); CombinePaths(path1, path3); CombinePaths(path3, path2); CombinePaths(path4, path2); CombinePaths(path5, path2); CombinePaths(path6, path2); CombinePaths(path7, path8); CombinePaths(path1, path8); } private static void CombinePaths(string p1, string p2) { try { string combination = Path.Combine(p1, p2); Console.WriteLine("When you combine '{0}' and '{1}', the result is: {2}'{3}'", p1, p2, Environment.NewLine, combination); } catch (Exception e) { Console.WriteLine("You cannot combine '{0}' and '{1}' because: {2}{3}", p1, p2, Environment.NewLine, e.Message); } Console.WriteLine(); } When you combine 'c:\temp' and 'subdir\file.txt', the result is: 'c:\temp\subdir\file.txt' When you combine 'c:\temp' and 'c:\temp.txt', the result is: 'c:\temp.txt' When you combine 'c:\temp.txt' and 'subdir\file.txt', the result is: 'c:\temp.txt\subdir\file.txt' When you combine 'c:^*&)(_=@#'\^&#2.*(.txt' and 'subdir\file.txt', the result is: 'c:^*&)(_=@#'\^&#2.*(.txt\subdir\file.txt' When you combine '' and 'subdir\file.txt', the result is: 'subdir\file.txt' You cannot combine '' and 'subdir\file.txt' because: Value cannot be null. Parameter name: path1 When you combine 'c:/temp/xxx.abc' and 'filename.txt', the result is: 'c:/temp/xxx.abc\filename.txt' When you combine 'c:\temp' and 'filename.txt', the result is: 'c:\temp\filename.txt'

Simple ASP.Net

		

When NOT using articlebehind the functions must be placed within a <script runat=server> blocks

Eg
<script language="C#" runat=server>
    void DoSomething() 
    {
        Response.Write("Hello World!");
    }
</script>

<%
    DoSomething();
%>


ASP
<%
    ' Below line outputs: "45"
    Response.Write Request.QueryString("value")
%>
In ASP.NET this is written as follows
Become
<%
    // Below line outputs: "45, 600"
    Response.Write(Request.QueryString["value"]);
%>


Reading Resource Files

		

Reading from Resource Files using ResourceManager

If you have a resource in your application ("MyApplication") with the name of "res.resx" do the following: 
ResourceManager rm = new ResourceManager("MyApplication.res", Assembly.GetExecutingAssembly()) 
string s = rm.GetString("TheKey"); 

Dynamically loading and using satellite resource assemblies

Assembly ass = Assembly.Load("AssemblyContaingResource); 
ResourceManager rm = new ResourceManager("SatelliteResource.res", ass); 
string s = rm.GetString("TheKey"); 


Abstract Classes and Abstract Methods

		

Abstract Classes and Abstract Methods
Abstract Classes CANNOT be instantiated. Only a class derived from an abstract class can be.
Can have methods declared as 'abstract'. An implementation CANNOT be defined for an abstract method ONLY the method signature.
All methods of an abstract class are implicitly 'virtual' and require use of 'override' keyword for their behaviour to be overriden

public abstract class AbstractClass
{
  // NON abstract method, implementation is defined but can be overridden
  public void NonAbstractMethod()
  {
    Console.WriteLine("Non-Abstract Method");
  }
  public abstract void AbstractMethod(); // An abstract method. Must be implemented by a deriving class in order that it can be instantiated.
}'


class ConcreteClass1 : public AbstractClass
{
  public override void AbstractMethod()
  {
    Console.WriteLine("Abstract Method Overriden");
  }
}


class ConcreteClass2 : public AbstractClass
{
  public override void NonAbstractMethod()
  {
    Console.WriteLine("Non-Abstract Method Override");
  }

  public override void AbstractMethod()
  {
    ...
  }
}

		

// Use StringBulder class to build up a string rather than appending many strings together. 
Having said that why does StringBuilder not have a format method? - It does AppendFormat() method

using System.Text;

    public override string ToString()
    {
      StringBuilder sb = new StringBuilder(base.ToString());
      sb.Append(".");
      sb.Append(m_Reason.ToString());
      return sb.ToString();
    }

Manipulating Filenames with Path

		

Use the Path Class to manipulate full path directory filenames
The use of @ to specify explicit strings is useful here because the you dont 
have to use '\\' notation.

Using System.IO;


string bareFilename = Path.GetFileNameWithoutExtension(bmpPath);
string ext = Path.GetExtension(bmpPath);

      string thumbnailFileName = Path.GetDirectoryName(bmpPath) + @"\" +
        Path.GetFileNameWithoutExtension(bmpPath) +
        "_thumb" + 
        Path.GetExtension(bmpPath);


Note 

File.Exists(filname);  // To check if a file exists
Directory.Exists(path) // To check if a dircetory exists

How To Calculate the Size of a New Image while Keeping the Aspect Ratio

		

    // The article will keep the aspect ratio of the image during resizing
    static public Size CalcSizeToFit(Size target, Size src)
    {
      float sfh = (float)target.Height/(float)src.Height;
      float sfw = (float)target.Width/(float)src.Width;
      float sf = Math.Min(sfh, sfw);
      Size sizeToFit = new Size((int)Math.Round((float)src.Width*sf),
        (int)Math.Round((float)src.Height*sf) );
      return sizeToFit;
    }


Using the Bitmap GetThumbnailImage() to create Image Thumbnails

		


     public bool ThumbnailCallback()
     {
          return false;
     }

    public Image CreateThumbnail(Bitmap bmp, string thumbnailFileName, Size max)
    {
      Image.GetThumbnailImageAbort myCallback =
        new Image.GetThumbnailImageAbort(ThumbnailCallback);
      Size imSize = CalcSizeToFit(max, bmp.Size);
      Image thumbnail = bmp.GetThumbnailImage(
        imSize.Width, imSize.Height, myCallback, IntPtr.Zero);
      return thumbnail;
    }


Resizing an Image at High Quality

		

// The following article resizes an image to fit a given target size
// It uses high quality bicubic interpolation to produce the best image quality
    static public Image ResizeImage(Image srcImage, Size targetSize)
    {
      Rectangle srcRect  = new Rectangle(0, 0, srcImage.Width, srcImage.Height);

      Size sizeToFit = CalcSizeToFit(targetSize, srcImage.Size);
      Rectangle destRect = new Rectangle(0, 0, sizeToFit.Width, sizeToFit.Height);

      Bitmap bmPhoto = new Bitmap(sizeToFit.Width, sizeToFit.Height, PixelFormat.Format24bppRgb);
      bmPhoto.SetResolution(srcImage.HorizontalResolution, srcImage.VerticalResolution);

      Graphics resizedImage = Graphics.FromImage(bmPhoto);
      resizedImage.Clear(Color.White);
      resizedImage.InterpolationMode = InterpolationMode.HighQualityBicubic;

      resizedImage.DrawImage(srcImage, 
        destRect, 
        srcRect, 
        GraphicsUnit.Pixel);

      grPhoto.Dispose();
      return bmPhoto;
    }


Launching or Spawing other Executables in .Net

		

To start an application in C# use the System.Diagnostics.Process class. 
Like this:
QUickstart an appplication:

using System.Diagnostics;

...

    Process.Start("Path to executable")
    Process.Start(@"C:\somedirectory"); // Open an explorer window at "C:\somedirectory"
    Process.Start("IExplore.exe", @"http://www.google.com/"); // Open internet explorer at google

    
To start the executable with some parameters:

    ProcessStartInfo psi = new ProcessStartInfo("IExplore.exe");
    startInfo.WindowStyle = ProcessWindowStyle.Minimized;
    startInfo.Arguments = "www.google.com";
    Process.Start(psi);
            

How to Set the Quality Parameter when Saving a JPEG Image in .NET

		
#using System.Drawing;
#using System.Drawing.Imaging;


// A little cheat copied directly from MSDN
http://msdn.microsoft.com/msdnmag/issues/03/07/CuttingEdge/default.aspx
      ImagearticlecInfo GetEnarticlerInfo(string mimeType)
      {
          int j;
          ImagearticlecInfo[] enarticlers;
          enarticlers = ImagearticlecInfo.GetImageEnarticlers();
          for(j = 0; j < enarticlers.Length; ++j)
          {
              if(enarticlers[j].MimeType == mimeType)
                  return enarticlers[j];
          }
          return null;
      }


      private void _SaveImage(Image img, string fileName, long qualityLevel)
      {
          string mimeType = "image/jpeg";
          ImagearticlecInfo jpegarticlecInfo = GetEnarticlerInfo(mimeType);

          // Set the quality kevel
          System.Drawing.Imaging.Enarticler qualityEnarticler = System.Drawing.Imaging.Enarticler.Quality;
          EnarticlerParameter ratio = new EnarticlerParameter(qualityEnarticler, qualityLevel);

          // Add the quality parameter to the list
          EnarticlerParameters articlecParams = new EnarticlerParameters(1);
          articlecParams.Param[0] = ratio;

          // Save to JPG
          img.Save(fileName, jpegarticlecInfo, articlecParams);   
      }


Reading Application Settings from a Configuration File

		


    private void _ReadAppSettingsExample()
    {
      /*
// Reads the follwong config file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<appSettings>
		<add key="key1" value="my key1 value" />
		<add key="key2" value="my key2 value" />
		<add key="key3" value="12345" />
		<add key="key4" value="true" />
	</appSettings>
</configuration>
       */
      NameValueCollection settings;
      AppSettingsReader   settingreader;
      string              key1, key2;
      int                 key3;    
      bool                key4;

      //1.) use ConfigurationSettings class to retrieve
      //    appSettings nodes in the web or app.config file
      //    which has methods for discovering the settings
      //    in the config file if not already known as well
      //    as retrieving setting values as strings.
      settings = ConfigurationSettings.AppSettings;

      //retrieve the value of key1
      key1 = settings["key1"];

      //retrieve the value of key2
      key2 = settings["key2"];

      //print the values of both keys to the console
      Console.WriteLine("{0}\r\n{1}", key1, key2);

      //loop through every setting in the .config file
      foreach(string keyname in settings.AllKeys)
      {
        //print name and value of app setting
        Console.WriteLine("{0}: {1}", keyname, settings[keyname]);
      }

      //cleanup
      settings = null;


            

      //2.) use AppSettingsReader to read appSettings nodes
      //    in the web or app.config file as types other than
      //    strings but you must know the name of the setting(s)
      //    you want ahead of time.
      settingreader = new AppSettingsReader();

      //retrieve a setting as a boolean
      key4 = (bool) settingreader.GetValue("key4", typeof(bool));

      //retrieve a setting as an int
      key3 = (int) settingreader.GetValue("key3", typeof(int));

      //cleanup
      settingreader = null;

      //print the values to the console
      Console.WriteLine("{0}\r\n{1}", key3, key4);
    }


Configuration Files In Asp.Net

		

<configuration>
  <appSettings>
    <add key="FlAspRoot" value="http://rbov.europe.webmatrix.net/fsl/" />
  </appSettings>
</configuration>

The ConfigurationSettings object exposes an AppSettings property that can be used to retrieve these settings: 
<%@ Import Namespace="System.Configuration" %>

<script language="C#" runat="server">

    void Page_Load(Object Src, EventArgs E ) 
    {
        ...
        String FlAspRoot = ConfigurationSettings.AppSettings["FlAspRoot"];
    }

</script>

Readonly Keyword

		

The readonly keyword is different from the const keyword. A const field can 
only be initialized at the declaration of the field. A readonly field can be
initialized either at the declaration or in a constructor. Therefore, 
readonly fields can have different values depending on the constructor used.
Also, while a const field is a compile-time constant, the readonly field can
be used for runtime constants as in the following example:

public static readonly uint l1 = (uint) DateTime.Now.Ticks;


public static readonly string s_OriginalPixelFilesFolder = s_DataFilesFolder + @"OriginalPixelFiles\" ;

Constructors calling Constructors

		
Whats the syntax for a constructor calling another constructor in C++?

In C# Constructors can call other constructors

eg:

	public EnterTextForm()
	{
		//
		// Required for Windows Form Designer support
		//
		InitializeComponent();
	}

	public EnterTextForm(string Title)
	: this()
	{
		this.Text = Title;
	}

String Method Return Values

		What must you be aware of when using string methods like 'Replace()' in C#?
		

Careful with .Net string class method Semantics

Eg: string sopInstanceUID = "1.3.51.0.7.14034843552.19164.58435.41639.25817.41592.22182.qs.xml" string modifiedstring = sopInstanceUID.Replace(".qs.xml", ""); // Want to remove the ".qs.xml" part Now modifiedstring is "1.3.51.0.7.14034843552.19164.58435.41639.25817.41592.22182" but sopInstanceUID is still "1.3.51.0.7.14034843552.19164.58435.41639.25817.41592.22182.qs.xml" The modified string is passed back as a return value, the original is not modified!

Using MessageBox

		
How do you invoke a MessageBox in C#
using System.Windows.Forms; 


    MessageBox.Show("Exception not thrown", "Message",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);

Temporary Filenames and the Temp Directory

		
Whats the class and method for creating a temporary filename and finding the Temporary files directory?
Whats the class for manipulating filenames? and what System object does it reference?

using System.IO;
    
    string fileName = @"SourceSerialized.xml";
    string tempDir = Path.GetTempPath();
    string fullPath = Path.Combine(tempDir, fileName);
    // or
    string fullPath = Path.Combine(Path.GetTempPath(), fileName);

    // For completely random filename
    string tempfn = Path.GetTempFileName();


Events In C#

		

Define a signature for the event:
  public delegate void IpChangedEventHandler(object sender, EventArgs e);

Put the event on an interface if required
  public interface IImageProcessor
  {
    event IpChangedEventHandler OnIpChangedEvent;
    ...
  }

On the SOURCE class, ie the one that fires the events, declare the event
  class EventGenerator : IImageProcessor
  {
    ...
    public event IpChangedEventHandler OnIpChangedEvent;
   

    // This is optional but it makes the process of firing events more robust. One of the 
    // biggest source of bugs in c# is trying to fire an event when the event handler is null
    private void _FireIpChangedEvent(eMusica1IpChanged reason)
    {
        if (!ReferenceEquals(OnIpChangedEvent, null))
            OnIpChangedEvent((object) this, new MyEventArgs(reason));
    }
  
    public void SomeFunc()
    {
      ...
      if (!ReferenceEquals(OnIpChangedEvent, null))
          OnIpChangedEvent(this, new EventArgs()); // Fire the event within the source class when required
      // OR using the event firer
      _FireIpChangedEvent(eMusica1IpChanged reason);
    }
  }


On the SINK class, ie the one that receives the events, declare an event handler and connect it to the event firer
  public class DrawingSurface()
  {
    // The event SINK must have the same signature as the event
    private void OnEventDoSomething(Object Sender, EventArgs e)
    {
       // React to the event
    }

    m_EventGenerator = new EventGenerator();
    // Connect the event SOURCE to the event SINK
    m_EventGenerator.OnIpChangedEvent += new IpChangedEventHandler(OnEventDoSomething);

  }


Custom Serialization C#

		
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
// Reference to the Binary format for a binary file
//using System.Runtime.Serialization.Formatters.Binary;

	[Serializable]
	public class DrawingSurface : ITransformation, IDisposable, IIdentity, ISerializable 
        {
...
        #region ISerialization Implementation

        //Deserialization constructor.
        public DrawingSurface(SerializationInfo info, StreamingContext ctxt)
        {
            BackGroundColor = (Color)info.GetValue("BackgroundColor", typeof(Color));
            smoothingmode = (SmoothingMode)info.GetValue("SmoothingMode", typeof(SmoothingMode));
            drawingEffect = (DrawingEffect)info.GetValue("DrawingEffect", typeof(DrawingEffect));
            Rect = (Rectangle)info.GetValue("Rectangle", typeof(Rectangle));
        }
        
        //Serialization function.
        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("BackgroundColor", BackGroundColor);
            info.AddValue("SmoothingMode", smoothingmode);
            info.AddValue("DrawingEffect", drawingEffect);          
            info.AddValue("Rectangle", Rect);          
        }

        #endregion ISerialization Implementation
produces the following Soap Xml file:

<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <a1:DrawingSurface id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/Agfa.ADCQS.ImageDisplay.ImagingCore/Agfa.ADCQS.ImageDisplay.ImagingCore%2C%20Version%3D3.0.497.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3D865fd83f349e9af5"> <BackgroundColor xsi:type="a2:Color" xmlns:a2="http://schemas.microsoft.com/clr/nsassem/System.Drawing/System.Drawing%2C%20Version%3D1.0.5000.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db03f5f7f11d50a3a"> <value>0</value> <knownColor>35</knownColor> <state>1</state> <name xsi:null="1"/> </BackgroundColor> <SmoothingMode xsi:type="a3:SmoothingMode" xmlns:a3="http://schemas.microsoft.com/clr/nsassem/System.Drawing.Drawing2D/System.Drawing%2C%20Version%3D1.0.5000.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db03f5f7f11d50a3a">AntiAlias</SmoothingMode> <DrawingEffect xsi:type="a4:DrawingEffect" xmlns:a4="http://schemas.microsoft.com/clr/nsassem/Agfa.ADCQS.ImageDisplay.ImagingCore.Interfaces/Agfa.ADCQS.ImageDisplay.ImagingCore%2C%20Version%3D3.0.497.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3D865fd83f349e9af5">Shadowed</DrawingEffect> <Rectangle xsi:type="a2:Rectangle" xmlns:a2="http://schemas.microsoft.com/clr/nsassem/System.Drawing/System.Drawing%2C%20Version%3D1.0.5000.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db03f5f7f11d50a3a"> <x>18</x> <y>150</y> <width>1148</width> <height>511</height> </Rectangle> </a1:DrawingSurface> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

Using Surrogates to Serialize non-serializable classes

		

Our Test Routine
        private void _TestSerializeToFile()
        {
            Stream stream = File.Open("SerializeToSoap.xml", FileMode.Create);
            SoapFormatter formatter = new SoapFormatter();
            _Serialize(stream, formatter);
            stream.Close();
        }

        public void _Serialize(Stream stream, IFormatter formatter)
        {
            m_SourceSurface.SourceChangedEvent -= new SourceChangedEventHandler(OnSourceChanged);
            // Create a new Surrogate Selector
            SurrogateSelector ss = new SurrogateSelector();
            // ADd the Pen Serializer to it
            ss.AddSurrogate(typeof(Pen),
                            new StreamingContext(StreamingContextStates.All),
                            new PenSerializer());
            ISurrogateSelector oldss = formatter.SurrogateSelector;
            // Attach the SurrogateSelector to the formatter
            formatter.SurrogateSelector = ss;
            formatter.Serialize(stream, m_SourceSurface);
            // Remove the SurrogateSelector from the formatter
            formatter.SurrogateSelector = oldss;
            // Optionally remove the surrogate serializer from the articleviously created surrogate selector  
            ss.RemoveSurrogate(typeof(Pen),
                               new StreamingContext(StreamingContextStates.All));
            m_SourceSurface.SourceChangedEvent += new SourceChangedEventHandler(OnSourceChanged);
        }



// Heres a simple surrogate serializer for a pen. 
// It only covers the situation when the Color and the Width are used to define the Pen.
    sealed class PenSerializer : ISerializationSurrogate
    {
        #region ISerializationSurrogate Members

        public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
        {
            Pen p = (Pen) obj;
            info.AddValue("Color", p.Color);
            info.AddValue("Width", p.Width);
        }

        public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
        {
            Pen p = (Pen) obj;
            p.Color = (Color)info.GetValue("Color", typeof(Color));
            p.Width = (float)info.GetValue("Width", typeof(float));
            //p.DashPattern = (float[])info.GetValue("DashPattern", typeof(float[]));
            return p;
        }

        #endregion

    }

Simple Serialization in .Net

		
This is the simplest form of Serialization. This example serialises to Soap which is an XML
format. The reason for serialzing to this format is that the file is more readable.
A reference to the System.Runtime.Serialization.Formatters.Soap component is needed.

using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
// Reference to the Binary format for a binary file
//using System.Runtime.Serialization.Formatters.Binary;


    public class SimpleSerializationTester
    {

        [Serializable]
        class SimpleSerializationCandidate
        {
            private byte byteval = 0;
            private short shorty = short.MinValue;
            private int intval = -5;
            private uint uintval = 5;
            private long longval = long.MaxValue;
            private string str = "Some string value";
            private Color m_BackgroundColor = Color.Black;
            private System.Drawing.Bitmap m_DispSurfaceBmp = null;
            private SmoothingMode m_smoothingmode = SmoothingMode.Default;
            private Rectangle m_AreaRect = new Rectangle(0, 0, 0, 0);
            [NonSerialized()] // To mark an attribute as not to be serialized
            private string m_NonSerializable = "Dont serialize me";

        }

        static public void TestSerializeToFile()
        {
            // Open a file and serialize the object into it in binary format.
            // EmployeeInfo.osl is the file that we are creating. 
            // Note:- you can give any extension you want for your file
            // If you use custom extensions, then the user will now 
            //   that the file is associated with your program.
            SimpleSerializationCandidate st = new SimpleSerializationCandidate();
            Stream stream = File.Open("SerializeToSoap.xml", FileMode.Create);
            SoapFormatter formatter = new SoapFormatter();
           
            Debug.WriteLine("Serializing Object");
            formatter.Serialize(stream, st);
            stream.Close();
        }

        static public void TestDeSerializeFromFile()
        {
            SimpleSerializationCandidate st = null;
            Stream stream = File.Open("SerializeToSoap.xml", FileMode.Open);
            SoapFormatter formatter = new SoapFormatter();       
            Debug.WriteLine("Deserializing Object");
            st = (SimpleSerializationCandidate)formatter.Deserialize(stream);
            stream.Close();
        }

    }


produces this file

<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <a1:SimpleSerializationTester_x002B_SimpleSerializationCandidate id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/ImagingCoreTest/WinTester%2C%20Version%3D1.0.1243.14956%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"> <byteval>0</byteval> <shorty>-32768</shorty> <intval>-5</intval> <uintval>5</uintval> <longval>9223372036854775807</longval> <str id="ref-4">Some string value</str> <m_BackgroundColor> <value>0</value> <knownColor>35</knownColor> <state>1</state> <name xsi:null="1"/> </m_BackgroundColor> <m_DispSurfaceBmp xsi:null="1"/> <m_smoothingmode>Default</m_smoothingmode> <m_AreaRect> <x>0</x> <y>0</y> <width>0</width> <height>0</height> </m_AreaRect> </a1:SimpleSerializationTester_x002B_SimpleSerializationCandidate> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

Override Paint Method on Form

		

        // Example of Overriding OnPaint in a Form
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 
        {
            Graphics g = e.Graphics;
            _Render(g);           
        }

        private void _Render(Graphics ds)
        {
            // Draw rectangle around client rectangle and text in centre
            Rectangle rect = this.ClientRectangle;
            rect.Height -= 1; 
            rect.Width  -= 1; 
            using (Font font = new Font("Arial", 12))
            {
                StringFormat sf = new StringFormat();
                sf.Alignment = StringAlignment.Center;
                sf.LineAlignment = StringAlignment.Center;
                ds.DrawString(
                    "Paint Test", 
                    font, 
                    (SolidBrush)Brushes.Black, 
                    rect, 
                    sf);                            
            }
            ds.DrawRectangle(Pens.Black, rect);
        }


Using A Modal Dialog

		

    EnterTextForm TextForm = new EnterTextForm();
    if (TextForm.ShowDialog(this) == DialogResult.OK)
    {
        // OK selected
        ((Grid)l_Annotation).CellSize = float.Parse(TextForm.AnnotationText);
    }
    else
    {
        l_Annotation = null; // Dump the unrequired text annotation
    }


Using A Modaless Dialog

		

        // Declare the modeless dialog
        private MagnifyingGlassForm m_MagFrm = null;


        // Creating and showing the modeless dialog
        if (m_MagFrm == null)
        {
          m_MagFrm = new MagnifyingGlassForm();
          m_MagFrm.Owner = this; // IMPORTANT Set the owner of the modeless dialog 
          m_MagFrm.Show(); // Show the modeless dialog
        }

        ...

        // To just hide the modeless dialog use Hide() method
        m_MagFrm.Hide()

        ...

        // Terminating the Modeless Dialog
        if (m_MagFrm != null)
        {
          m_MagFrm.Close();
          m_MagFrm.Dispose();
          m_MagFrm = null;
        }

using keyword

            

C# provides a Using statement which ensures that Dispose will be called at the earliest possible time.When the close brace is reached the Dispose method will be called on the object automatically. No matter how control leaves the Using statement, Dispose is called. It is as if there were an implicit try-catch-finally block.

public void MyMethod() { using (Font theFont = new Font("Arial", 10.0f)) { // use theFont } // compiler will call Dispose on theFont Font anotherFont = new Font("Courier",12.0f); using (anotherFont) { // use anotherFont } // compiler calls Dispose on anotherFont }

Using Image.GetThumbnailImage

		        public bool ThumbnailCallback()
        {
            return false;
        }

        private void button2_Click(object sender, System.EventArgs e)
        {
            if (m_Image == null)
                return;

            float w = m_Image.Width;
            float h = m_Image.Height;
            Image.GetThumbnailImageAbort myCallback =
                new Image.GetThumbnailImageAbort(ThumbnailCallback);
            if (w > h)
                m_Thumbnail = m_Image.GetThumbnailImage(100, (int)(100*h/w + 0.5f), myCallback, IntPtr.Zero); 
            else
                m_Thumbnail = m_Image.GetThumbnailImage((int)(100*w/h + 0.5f), 100, myCallback, IntPtr.Zero); 
        }

Calling Forms As Dialogs

            

Sample:

EnterTextForm TextForm = new EnterTextForm(); Text textAnn = new Text(); TextForm.AnnotationFont = textAnn.Font; DialogResult res = TextForm.ShowDialog(this); if (res == DialogResult.OK) { textAnn.theText = TextForm.AnnotationText; textAnn.Font = TextForm.AnnotationFont; l_Annotation = textAnn; } else { textAnn = null; // Dump the unrequired text annotation }

In this case in the form properties we need to set the 'AcceptButton' and 'CancelButton' properties

Arrays

            

Declaring an array:

Pen[] pen = new Pen[1000];

Getting Direct Access To Bitmap Data

		
    unsafe // Get direct access to the bitmaps bits
    {   
        BitmapData bitmapData = m_DestImageBmp.LockBits(
            new Rectangle(0, 0, visibleImageArea.Width, visibleImageArea.Height),
            ImageLockMode.WriteOnly,
            PixelFormat.Format8bppIndexed);
        try
        {   
            // get the pointer to the image bits
            // this is the unsafe operation
            byte* pBits = (byte*)bitmapData.Scan0;
            if (bitmapData.Stride < 0)
            {
                // If the Stride is negative, Scan0 points to the last 
                // scanline in the buffer. To normalize the loop, obtain
                // a pointer to the front of the buffer located (Height-1)
                // scanlines articlevious.
                pBits = (byte*)bitmapData.Scan0 + bitmapData.Stride * (bitmapData.Height-1);
            }
            ushort pitch = (ushort)Math.Abs(bitmapData.Stride);
            IntPtr pixelData = (IntPtr)pBits;
            ushort height = (ushort)bitmapData.Height;
            ushort width = (ushort)bitmapData.Width;
            
            DoSomething(pixelData, pitch, width, height); // Do something with the bitmap data
        }
        finally
        {   // Make sure the bitmap data is unlocked
            m_DestImageBmp.UnlockBits(bitmapData);
        }
    }

Pattern for Implementing IDisposable Interface

		
For the base class add the following;
#region IDispose Implementation

// In class constructor/destructor put the following article
// class MyClass: ... , IDisposable

//~MyClass()
//{
//    // Dispose but only dispose of unanaged resources
//    _Dispose(false);
//}

/// <summary>
// Implement Dispose method to delete or release all resources.
/// </summary>
public void Dispose()
{
    _Dispose(true);
}

/// <summary>
/// Implement thread and GC safe disposal of any used resources.
/// </summary>
protected virtual void _Dispose(bool disposeManaged)
{
    lock(this) // to assure thread safety
    { 
        try
        {
            // Check to see if Dispose has already been called.
            if(!m_DisposedFlag)
            {
                // If disposing equals true, dispose all managed resources.
                if(disposeManaged)
                {
                    // Take yourself off of the Finalization queue 
                    // to articlevent finalization article for this object
                    // from executing a second time.
                    GC.SuparticlessFinalize(this);
                
                    // Dispose MANAGED resources
                }

                // Dispose UNMANAGED resources. If disposing is false, 
                // only the following article is executed.

                m_DisposedFlag = true;
            }
        }
        finally
        {   
            // When inheriting from a IDisposable implementing class call Dispose on the base
            //base._Dispose(disposeManaged);
        }
    }
}

/// <summary>
/// Track whether Dispose has been called.
/// </summary>
private bool m_DisposedFlag = false;

#endregion IDispose Implementation
For futher DERIVED classes
#region IDispose Implementation
// In class destructor put the following article
//~MyClass()
//{
//    // Dispose but only dispose of unanaged resources
//    _Dispose(false);
//}

/// <summary>
/// Implement thread and GC safe disposal of any used resources.
/// </summary>
protected override void _Dispose(bool disposeManaged) // This line in derived classes
{
    lock(this) // to assure thread safety
    { 
        try
        {
            // Check to see if Dispose has already been called.
            if(!m_DisposedFlag)
            {
                // If disposing equals true, dispose all managed resources.
                if(disposeManaged)
                {
                    // Take yourself off of the Finalization queue 
                    // to articlevent finalization article for this object
                    // from executing a second time.
                    GC.SuparticlessFinalize(this);
                
                    // Dispose MANAGED resources
                }

                // Dispose UNMANAGED resources. If disposing is false, 
                // only the following article is executed.

                m_DisposedFlag = true;
            }
        }
        finally
        {   
            // When inheriting from a IDisposable implementing class call Dispose on the base
            base._Dispose(disposeManaged);
        }
    }
}

/// <summary>
/// Track whether Dispose has been called.
/// </summary>
private bool m_DisposedFlag = false;


#endregion IDispose Implementation

Using Ref & Out

		

An out parameter must be assigned before it is used; that is, it must be assigned by the callee. Example (using arrays):

public void MyMethod(out int[] arr) 
{
   arr = new int[10];   // definite assignment of arr
   // Can now Use arr
   arr[0] = ...
}

//Caller:
int[] arr = null;
MyMethod(arr);

Like all ref parameters, a ref parameter must be definitely assigned by the caller. Therefore, there is no need to be definitely assigned by the callee. Example (using arrays):

public void MyMethod(ref int[] arr) { // Create on demand if (arr == null) arr = new int[10]; // Otherwise use the passed referenced type arr[0] = 123; ... } //Caller: int[] arr = new int[10]; arr[9] = 5; MyMethod(arr); see Msdn site http://www.google.com/search?q=Programmer+Reference+Passing+Parameters http://www.ondotnet.com/pub/a/dotnet/2002/11/25/copying.html?page=3 - Copying cloning and marshalling in .Net 1. Passing value types by value void PassValueTypeByValue(int x) // The value type parameter x is passed by value. Changes to x will NOT affect the original value. 2. Passing value types by reference Yes void PassValueTypeByReference(ref int x) // The value type parameter x is passed by reference. Changes to x WILL affect the original value. 3. Passing reference types by value void PassReferenceTypeByValue(int[] arr) // The reference type parameter arr is passed by value. Changes to the attributes of arr WILL affect the original. // Trying to reassign the reference 'arr' will fail 4. Passing reference types by reference void PassReferenceTypeByReference(ref int[] arr) All changes affect the original. 5. Passing unassigned reference types. Use the out keyword. void PassReferenceTypeForInitialization(out int[] arr) "arr" it must be assigned by the callee before it is used. RPC/DCOM keyword C# equivalent remoting keyword [in] (default) [in,out] ref [out] out

ReadOnly Fields

		

Can declare a field as 'readonly' 
Eg. Declaring a static readonly string
        static private readonly string m_Name = "Bicubic";
Can also be initialised in the constructor (static constructor in this case)

Generic Message for a Caught Exception

		
    catch( Exception ex )
    {
        Trace.WriteLine(String.Format("### EXCEPTION {0} caught in {1}.{2}", 
            ex.Message,
            System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName,
            System.Reflection.MethodBase.GetCurrentMethod().Name));
        return XXX;
    }

Using foreach statement

            SOMETYPE[] hurray = new SOMETYPE [] {0,1,2,5,7,8,11};
      foreach (SOMETYPE  entry in hurray) 
      {
         // ... DoSomething with entry    
      }

Pinning An Array in Memory

		
...
    SOMETYPE[] SomeTypeArray;
...


    unsafe 
    {
        SOMETYPE* l_Dest;
        // pin the managed palette during the copy process using the 'fixed' statement.
        fixed(SOMETYPE* l_Pin = &SomeTypeArray[0])
        {
            SOMETYPE* l_Source = l_Pin;
            // copy palette
            l_Dest = (SOMETYPE*)GetSomeTypeDest();
            
            if (l_Dest == null) return false;
    
            for (short f = 0; f < 256 ; f++)
            {   
                *l_Dest++ = *l_Source++;
            }

        }
    }

Using Reflection on the Fly

		
Usefull for getting information about the scope of a call dynamically
Eg:
Method "public unsafe bool Render(Graphics g)"
in class "DisplayArea"
in namespace "Agfa.ADCQS.ImageDisplay.ImagingCore"
yields the following:
    String s1 = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName;
// produces "Agfa.ADCQS.ImageDisplay.ImagingCore.DisplayArea"
    String s2 = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString();
// produces "Agfa.ADCQS.ImageDisplay.ImagingCore.DisplayArea"
    String s3 = System.Reflection.MethodBase.GetCurrentMethod().ToString();
// produces "Boolean Render(System.Drawing.Graphics)"
    String s4 = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name;
// produces "DisplayArea"
    String s5 = System.Reflection.MethodBase.GetCurrentMethod().Name ;
// produces "Render"

More reflection. This time its used to get the type of a object
whos only reference to it we have is that of a interface from 
which it is derived

    string tn = null;
    IInterpolationStrategy ims = m_Image.InterpolationStrategy;
    if (ims != null)
    {
        Type type = ims.GetType();
        tn = type.Name;
        // or 
        // tn = ims.GetType().Name
     }
     BilinearMenuItem.Checked = (string.Compare(tn, typeof(Bilinear).Name) == 0);
     SubSampleMenuItem.Checked = (string.Compare(tn, typeof(SubSample).Name) == 0);


Using String.Format on the Fly

		
// This is a useful technique for placing a formatted string 
// as an argument to some other object method.
// Its useful for Tracing and Logging etc.

    Trace.WriteLineIf(TraceFileMappedBuffers.TraceInfo
                     ,"Could not map View of file" 
                     ,String.Format("FileMappedBuffer.Create({0}) ", m_Id));


Enumerations

		



// Basic
public enum Bool 
{
    False = 0,
    True
};

// Using enumerations as flags
[Flags]
public enum Flags
{
    NoAccess = 0,
    Read     = 1,
    Write    = 2
};
Flags myflags = Flags.Read | Flags.Write


Using Debug.Assert

		
1. Set a reference to the System.Diagnostics classes.
using System.Diagnostics;

Debug.Assert(xxx == 0);
Debug.Assert(xxx == 0, "some message");
Debug.Assert(xxx == 0, "some message", "another part of the message");

Switchable Tracing

		
1. Create a trace switch
static private TraceSwitch XXX = new TraceSwitch("XXX", "Description of your trace switch");

2. Add a Application config file. On the project using the context menu select "Add=>Add New Item..." and then select 
"Application Configuration"

3. Set the level of the trace in the config file of the application
<configuration>
  <system.diagnostics>
    <switches>
         <!-- These switches control general messages. In order to 
         receive general trace messages change the value to the 
         appropriate level. 
         "1" gives error messages, 
         "2" gives errors  and warnings, 
         "3" gives more detailed error information, and 
         "4" gives verbose trace information -->
      <add name="XXX" value="4" />
    </switches>
  </system.diagnostics>
</configuration>


To use the trace switch (in debug and release modes)
    Trace.WriteLineIf(XXX.TraceInfo, "Create - Destination Buffer REUSED");
OR in debug only mode
    Debug.WriteLineIf(XXX.TraceInfo, "Create - Destination Buffer REUSED");


Properties

		

    public bool Enabled
    {
        get
        {
            return m_Enabled;
        }

        set
        {
            m_Enabled = value;
        }
    }

Can have indexers
    public IAnnotation Annotation[uint index]
    {
        get
        {
                            // Test to see if index is in range!
            return  ... ;
        }

        set
        {
                            // Test to see if index is in range!
            ... = value;
        }
    }

Switch Statement

		

    switch (AnnotationsListBox.Text)
    {
        case "StraightLine":
        case "Line":
            m_AnnManager.AddAnnotation(new Line());
        break;
        case "Arrow":
            m_AnnManager.AddAnnotation(new Arrow());
        break;
        default:
            // Nothing selected
        break;
    }

Using Trace and Debug

		
Add
using System.Diagnostics;

No new References needed

To Use
    Trace.WriteLine(String.Format("Delete - Releasing {0} bytes",m_Size));
    Trace.WriteLine("Create - Destination Buffer REUSED");

    Debug.Assert((pt.X == 121) && (pt.Y == 179));
    Debug.WriteLine("CDisplayArea::_NotifyImageUpdater - An Image updater changed");

The "Trace" class is in both Release and Debug builds.
The "Debug" class is in Debug builds ONLY.

XML Read/Writer Demo In .Net

		

using System;
using System.Xml;
using System.IO;

public class Obj1
{
    int i;
    string s;
    
    public Obj1 (int i, string s)
    {
        Console.WriteLine ("Obj1 constructor: " + i + " " + s);
        this.i = i;
        this.s = s;
    }

    public Obj1 (XmlReader r)
    {
        r.ReadStartElement("Obj1");
        r.ReadStartElement("i"); 
        i = r.ReadInt32();
        r.ReadEndElement();
        r.ReadStartElement("s"); 
        s = r.ReadString();
        r.ReadEndElement();
        r.ReadEndElement();
        Console.WriteLine ("Obj1 constructor from XML-file: " + i + " " + s);
    }
    
    public void WriteXml (XmlWriter w)
    {
        w.WriteStartElement("Obj1");
        w.WriteElementInt32("i",i);
        w.WriteElementString("s",s);
        w.WriteEndElement();
    }
}


public class Class1
{
    public static void Main(string[] args)
    {
        Obj1 o1 = new Obj1 (1,"abc");

        // ---- Save objects in XML-file ----
        XmlTextWriter w = new XmlTextWriter ("test.xml", null); 
        w.Formatting = Formatting.Indented;

        w.WriteStartDocument();
            w.WriteStartElement("Test");
                o1.WriteXml (w);
            w.WriteEndElement();
        w.WriteEndDocument();
        w.Close();

        // Produces this:
        //<?xml version="1.0"?>
        //<Test>
        //  <Obj1>
        //    <i>1</i>
        //    <s>abc</s>
        //  </Obj1>
        //</Test>

        // ---- Read objects from XML-file -----
        XmlTextReader r = new XmlTextReader ("test.xml");
        r.WhitespaceHandling = WhitespaceHandling.None;

        r.Read();
        if (r.NodeType != XmlNodeType.XmlDeclaration) throw new ApplicationException("No XML declaration node");

        r.ReadStartElement("Test");
        while (true)
            if ((r.NodeType == XmlNodeType.EndTag) && (r.Name == "Test")) break;
            //----------------------------------------------
            else if (r.IsStartElement("Obj1")) new Obj1(r);
            //----------------------------------------------
            else throw new ApplicationException("Unknown node found");
    }
}


Does Rectangle.Inflate keep the rectangle centred

		

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 
{
    Graphics g = e.Graphics;
            
    // Q) What does Rectangle.Inflate do?
    // A) Inflates the rectangle relativeto its centre point
    // Create a rectangle.
    //Rectangle rect = new Rectangle(120, 200, 50, 50);
    // Draw the uninflated rect to screen.
    //g.DrawRectangle(Pens.Blue, rect);
    // Call Inflate.
    //Rectangle rect2 = Rectangle.Inflate(rect, 50, 50);
    // Draw the inflated rect to screen.
    //g.DrawRectangle(Pens.Red, rect2);

}


E-Mail me any comments, suggestions, ideas etc. HERE
Last updated 16 March 2004.