/* A Programmer's Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3 */ // 30 - Execution-Time Code GenerationLoading AssembliesMaking it Dynamic // copyright 2000 Eric Gunnerson // file=LogAddInToFile.cs // compile with: csc /r:..logdriver.dll /target:library logaddintofile.cs using System; using System.Collections; using System.IO; public class LogAddInToFile: ILogger { StreamWriter streamWriter; public LogAddInToFile() { streamWriter = File.CreateText(@"logger.log"); streamWriter.AutoFlush = true; } public void Log(string message) { streamWriter.WriteLine(message); } } //============================================================= // 30 - Execution-Time Code GenerationLoading Assemblies // copyright 2000 Eric Gunnerson // file=LogDriver.cs // compile with: csc /target:library LogDriver.cs using System; using System.Collections; public interface ILogger { void Log(string message); } public class LogDriver { ArrayList loggers = new ArrayList(); public LogDriver() { } public void AddLogger(ILogger logger) { loggers.Add(logger); } public void Log(string message) { foreach (ILogger logger in loggers) { logger.Log(message); } } } public class LogConsole: ILogger { public void Log(string message) { Console.WriteLine(message); } }
Language Basics
File to be used as a library assembly 2
/* C# Programming Tips & Techniques by Charles Wright, Kris Jamsa Publisher: Osborne/McGraw-Hill (December 28, 2001) ISBN: 0072193794 */ // Circle.cs -- File to be used as a library assembly // // Compile this file with the following command line: // C:>csc /t:module Circle.cs using System; namespace nsCircle { // A structure to define a Cartesian point. public struct POINT { public POINT (int x, int y) { cx = x; cy = y; } public int cx; public int cy; public override string ToString() { return (String.Format ("(" + cx + ", " + cy + ")")); } } public class clsCircle { // Two constructors to define the circle. public clsCircle (double radius, POINT center) { m_Center = center; m_Radius = radius; } public clsCircle (double radius, int cx, int cy) { m_Center.cx = cx; m_Center.cy = cy; m_Radius = radius; } public clsCircle () { m_Center.cx = 0; m_Center.cy = 0; m_Radius = 0; } public double Radius { get {return (m_Radius);} set {m_Radius = value;} } public POINT Center { get {return (m_Center);} set {m_Center = value;} } // Fields to contain circle data. POINT m_Center; private double m_Radius; // Constants to make life easier private const double pi = 3.14159; private const double radian = 57.29578; // Return the area of the circle public double Area { get {return (m_Radius * m_Radius * pi);} } // Return the diameter of the circle public double Diameter { get {return (2 * m_Radius);} } // Return the coordinates of a point on the circle at a given angle. public POINT PointOnCircle (double degrees) { POINT pt; double fAngle = degrees / radian; // Compute the x position of the point pt.cx = (int)((double) m_Radius * Math.Cos (fAngle) + 0.5); // Compute the y position of the point pt.cy = (int)((double) m_Radius * Math.Sin (fAngle) + 0.5); return (pt); } // Return the area of a slice determined by a given angle. public double AreaOfSlice (double degrees) { double fAngle = degrees / 57.29578; return (Area * fAngle / (2 * pi)); } } } // Geom.cs -- Demonstrates using an assembly. // // Build this program and the Circle assembly using // the following command sequence: // C:>csc /t:module Circle.cs // C:>sn -k Circle.snk // C:>al /keyfile:Circle.snk /version:1.0.0.0 /out:Circle.dll Circle.NetModule // C:>gacutil /i Circle.dll // C:>csc /r:circle.dll Geom.cs // using System; using nsCircle; namespace nsGeometry { class clsMain { static public void Main () { double angle = 32.6; // Create an instance of the circle class. clsCircle circle = new clsCircle (420, 0, 0); // Get the point on the circle at the angle. POINT pt = circle.PointOnCircle (angle); // Show the total area of the circle. Console.WriteLine ("The area of the circle is " + circle.Area); // Show the point. Console.WriteLine ("The point on the circle is at " + pt); // Show the area of the slice between 0 degrees and the angle. Console.WriteLine ("The area of the slice is " + circle.AreaOfSlice (angle)); } } }
File to be used as a library assembly
/* C# Programming Tips & Techniques by Charles Wright, Kris Jamsa Publisher: Osborne/McGraw-Hill (December 28, 2001) ISBN: 0072193794 */ // Circle.cs -- File to be used as a library assembly // // Compile this file with the following command line: // C:>csc /t:library Circle.cs using System; namespace nsCircle { // A structure to define a Cartesian point. public struct POINT { public POINT (int x, int y) { cx = x; cy = y; } public int cx; public int cy; public override string ToString() { return (String.Format ("(" + cx + ", " + cy + ")")); } } public class clsCircle { // Two constructors to define the circle. public clsCircle (double radius, POINT center) { m_Center = center; m_Radius = radius; } public clsCircle (double radius, int cx, int cy) { m_Center.cx = cx; m_Center.cy = cy; m_Radius = radius; } public clsCircle () { m_Center.cx = 0; m_Center.cy = 0; m_Radius = 0; } public double Radius { get {return (m_Radius);} set {m_Radius = value;} } public POINT Center { get {return (m_Center);} set {m_Center = value;} } // Fields to contain circle data. POINT m_Center; private double m_Radius; // Constants to make life easier private const double pi = 3.14159; private const double radian = 57.29578; // Return the area of the circle public double Area { get {return (m_Radius * m_Radius * pi);} } // Return the diameter of the circle public double Diameter { get {return (2 * m_Radius);} } // Return the coordinates of a point on the circle at a given angle. public POINT PointOnCircle (double degrees) { POINT pt; double fAngle = degrees / radian; // Compute the x position of the point pt.cx = (int)((double) m_Radius * Math.Cos (fAngle) + 0.5); // Compute the y position of the point pt.cy = (int)((double) m_Radius * Math.Sin (fAngle) + 0.5); return (pt); } // Return the area of a slice determined by a given angle. public double AreaOfSlice (double degrees) { double fAngle = degrees / 57.29578; return (Area * fAngle / (2 * pi)); } } } // Geom.cs -- Demonstrates using an assembly. // // Compile this program with the following command line: // C:>csc /r:circle.dll Geom.cs using System; using nsCircle; namespace nsGeometry { class clsMain { static public void Main () { double angle = 32.6; // Create an instance of the circle class. clsCircle circle = new clsCircle (420, 0, 0); // Get the point on the circle at the angle. POINT pt = circle.PointOnCircle (angle); // Show the total area of the circle. Console.WriteLine ("The area of the circle is " + circle.Area); // Show the point. Console.WriteLine ("The point on the circle is at " + pt); // Show the area of the slice between 0 degrees and the angle. Console.WriteLine ("The area of the slice is " + circle.AreaOfSlice (angle)); } } }
CreateDelegate and DynamicInvoke
using System; using System.Reflection; delegate void theDelegate(int arga, int argb); class MyClass { public void MethodA(int arga, int argb) { Console.WriteLine("MyClass.MethodA called: {0} {1}", arga, argb); } } class Starter { static void Main() { Type tObj = typeof(System.MulticastDelegate); MyClass obj = new MyClass(); Delegate del = Delegate.CreateDelegate(typeof(theDelegate), obj,"MethodA"); del.DynamicInvoke(new object[] { 1, 2 }); } }
Combining delegates Multiple delegates are combined using the Combine method, the plus operator (+), or the += assignment operator.
using System; public delegate void DelegateClass(); public class Starter { public static void Main() { DelegateClass del = MethodA; del += MethodB; del(); } public static void MethodA() { Console.WriteLine("MethodA..."); } public static void MethodB() { Console.WriteLine("MethodB..."); } }
Lifetime of outer variables is aligned with the delegate
using System; public delegate void DelegateClass(out int var); public class Starter { public static void Main() { DelegateClass del = MethodA(); int var; del(out var); del(out var); del(out var); Console.WriteLine(var); } public static DelegateClass MethodA() { int increment = 0; return delegate(out int var) { var = ++increment; }; } }
The publisher/subscriber relationship is a one-to-many relationship.
using System; class Publisher { public event EventHandler MyEvent; } public class Subscriber { public static void Handler(object obj, EventArgs args) { } public static void Main() { Publisher pub = new Publisher(); pub.MyEvent += Handler; // other processing } }