Translate

Thursday, 31 December 2009

Happy New Year

Mobile tweeting is the only resolution I have made for the new year 2010!

Monday, 9 November 2009

NUnit support for .Net 4.0

The fix has been committed and NUnit will support .Net 4.0 framework from ver. 2.5.3 or the future versions. And I am glad I contributed to the fix.

Friday, 28 August 2009

Unit Testing .Net 4.0 with TDD.Net

Hey,

Even if NUnit in its current form does not support .Net 4.0, there is a workaround with Test Driven.Net. Download, install and VS 2010 acknowledges Test Driven.Net and you can run your unit tests right inside VS 2010. It is as cool as NUnit.

Here is the code to test the RandomGenerator class:

using System;
using NUnit.Framework;
using RandomCalculator;
namespace ClassLibrary1
{
[TestFixture]
public class Class1
{
[Datapoints]
public int[] parametersForRandomGeneration = RandomCalculatorClass.GenerateRandomNumbers();
[Theory]
public void RandomNumbers(int x, int y, int z)
{
Assume.That(z > 0 && z <4);
if (z == 1)
{
Assert.That(x+y, Is.EqualTo(RandomCalculatorClass.add(x,y)));
}
else if (z == 2)
{
Assert.That(x * y, Is.EqualTo(RandomCalculatorClass.multiply(x, y)));
}
else if (z == 3)
{
Assert.That(x / y, Is.EqualTo(RandomCalculatorClass.divide(x, y)));
}
prevNumber = z;
}
}
}

Happy Unit Testing !:)

NUnit for .Net 4.0

Shucks! NUnit currently does not support .Net 4.0 assemblies or may be expectations are ahead !

Thursday, 27 August 2009

Parallel.For XML Parsing

Another example using Parallel.For. Depending upon the cores in your machine, you will find the code returning different results. MaxDegreeOfParallelism sets the max number of cores to be used for running the parallel forloop.

class Program
{
static void Main(string[] args)
{
XmlDocument xDoc = new XmlDocument();
xDoc.Load("e:\\JKTAgileAcademy_August2009\\cd_catalog.xml");
XmlNodeList title = xDoc.GetElementsByTagName("CD");
XmlNode xNode=null;
var options = new ParallelOptions { MaxDegreeOfParallelism = 2 };
Stopwatch sw=new Stopwatch();
sw.Start();
Parallel.For(0, title.Count, options, (j) => //() => title, (x, loop, xN) =>
{
xNode = title.Item(j);
Console.WriteLine("Inner XML from Nodelist" + xNode.InnerText);
j++;
}
);
sw.Stop();
Console.WriteLine("Time taken by parallel loop " + sw.ElapsedMilliseconds.ToString());
//sw.Reset();
sw.Start();
for (int i = 0; i < title.Count; i++)
{
xNode = title.Item(i);
Console.WriteLine(xNode.InnerText);
}
sw.Stop();
Console.WriteLine("Time taken by for loop " + sw.ElapsedMilliseconds.ToString());

Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}

Parallel Computing - .Net 4.0

Ah. I said, when i watched the TechEd cast in MSDN Tv, i can understand the difference between multi-threading and parallel computing correctly and the importance of cores in a CPU. But that is the only joy that you get from .Net 4.0!

I took the plunge, downloaded VS 2010 and wham !, the product literally explodes in your fingers (with a 2 GB dual core laptop)!! Context menus, intellisense menus fly in and out and the previous "system" and ctrl-space is now more polished with "sys" bringing up the menu! Ok, so fa so good!

I essayed into "paral.."ctrl-space and nothing appeared in the menu! You have to include System.Threading to be able to use the Parallel class. Ah, first step done! Next step that I was eager to try was the Parallel.For method. First, I thought of parsing a XML tree but then decided for a simpler approach - the traditional calculator! Here is the code:

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
//sw.Reset();
sw.Start();
Parallel.For(0,225, (x)=>
{
Task t2 = new Task(() =>
{

int[] w=GenerateRandomNumbers();
Calculate(w[0], w[1], w[2]);
});//,TaskCreationOptions.PreferFairness);

t2.Start();
t2.Wait();
});
sw.Stop();
Console.WriteLine("Finished parallel task in (milliseconds) - {0}",sw.ElapsedMilliseconds);
//sw.Reset();
sw.Start();
for (int i = 0; i < 225; i++)
{
int[] w = GenerateRandomNumbers();
Calculate(w[0], w[1], w[2]);
}
sw.Stop();
Console.WriteLine("Finished task in (milliseconds) - {0}", sw.ElapsedMilliseconds);

Console.ReadLine();
}
static int[] GenerateRandomNumbers()
{
Random r = new Random();
Random r1 = new Random();
Random r2 = new Random();
return new int[] { r.Next(150), r1.Next(100), r2.Next(4) };
}
static int add(int a, int b)
{
return a + b;
}
static int multiply(int a, int b)
{
return a * b;
}
static int divide(int a, int b)
{
return a / b;
}
static void Calculate(int x, int y, int operation)
{
switch (operation)
{
case 1:
Console.WriteLine("Added two numbers {0} ",add(x,y));
break;
case 2:
Console.WriteLine("Product of two numbers {0} ",multiply(x,y));
break;
case 3:
Console.WriteLine("Divided two numbers {0} ",divide(x,y));
break;
}
}
}


Notes:
1. Increase the loop condition value so that you can see more random number combination.

2. Aside from Parallel, the code above also dwells in Task - a class that is part of the System.Threading.Tasks namespace. A task is like a thread but unlike a thread it has more sophisticated provisions like scheduling, creation options etc.

3. //,TaskCreationOptions.PreferFairness);

Uncomment the above statement and you will see a rather reluctant execution of the loop. The intellisense guide is below:

A hint to TaskScheduler to schedule this task as fairly as possible, meaning the tasks scheduled early will run early and those later will run later!!
Happy .Net 4.0 programming!

4. With the above commented, you see that the Parallel FOr loop runs faster than the normal for loop.

Tuesday, 28 July 2009

Parallel Unit Testing with PNUnit

One of the great things about the coming version of NUnit is the integration of PNUnit - the parallel Unit Testing tool developed by codice.com.

With PNunit, you can distribute your tests across machines and test it for different load and stress scenarios. This distributed testing mechanism also helps in performing "smoke tests". The other advantages, to keep it brief, is that the team that uses PNUnit need not learn any new scripting language and can extend on its existing skill sets. This is also why PNUnit is called as NUnit Extensions.

The parallel execution of testsis possible through a configuration based framework where the configuration file (with an extension of ".conf") tells the framework the assembly name, the test fixture name, the machine ip, the port number - much like how a remoting configuration file would do.

The PNUnit framework is enabled by two components - an Agent that listens on a certain port and a Launcher, which launches the Unit Tests as specified in the .conf file.

The ease of use is further enhanced with the help of the familiar C# / NUnit type syntax. The example below shows the execution of the tests on two machines.

Copy the source code and build. The output assembly should be "pnunittests.dll" or even if it is not, make sure to change the name in the ".conf" file.

Copy the configuration code below into a file called "pnunittests.conf" and place all these files into the "pnunit" folder.


// PNUnitTests.dll

using System;
using System.Threading;
using NUnit.Framework;
using PNUnit.Framework;

namespace PNUnitTests
{

[TestFixture]
public class Testing
{
private string[] testParams;
[SetUp]
public void initTests()
{
testParams = PNUnitServices.Get().GetTestParams();
}
[Test]
public void FirstTest()
{

PNUnitServices.Get().InitBarrier("BARRIER");
// wait two seconds
System.Threading.Thread.Sleep(2000);
PNUnitServices.Get().WriteLine(
string.Format(
"FirstTest started with param {0}",
testParams[0]));
PNUnitServices.Get().EnterBarrier("BARRIER");
Assert.AreEqual(Convert.ToInt32(testParams[0]), Cmp.Add(15, 4));
}
[Test]
public void SecondTest()
{
PNUnitServices.Get().WriteLine(
"Second test will wait for first");
PNUnitServices.Get().InitBarrier("BARRIER");
// will wait for the first test
PNUnitServices.Get().WriteLine(
"First test should be started now");
Assert.AreEqual(Convert.ToInt32(testParams[0]), Cmp.Add(15, 4));
}

}
}

//Distributedtest.dll

using System;
using System.Threading;
using NUnit.Framework;
using PNUnit.Framework;

namespace DistributedTest
{
[TestFixture]
public class Class1
{
[Test]
public void TestOnAnotherMachine()
{
string[] testValues=PNUnitServices.Get().GetTestParams();
Assert.AreEqual(testValues[0], "Hello World!");
}
}
}

// pnunittests.conf
<?xml version="1.0" encoding="utf-8" ?>
<TestGroup>
<ParallelTests>
<ParallelTest>
<Name>SimpleTest</Name>
<Tests>
<TestConf>
<Name>FirstTest</Name>
<Assembly>pnunittests.dll</Assembly>
<TestToRun>PNUnitTests.Testing.FirstTest</TestToRun>
<Machine>localhost:8080</Machine>
<TestParams>
<string>19</string>
</TestParams>
</TestConf>
<TestConf>
<Name>SecondTest</Name>
<Assembly>pnunittests.dll</Assembly>
<TestToRun>PNUnitTests.Testing.SecondTest</TestToRun>
<Machine>localhost:8080</Machine>
<TestParams>
<string>19</string>
</TestParams>

</TestConf>
<TestConf>
<Name>DistributedTest</Name>
<Assembly>distributedtest.dll</Assembly>
<TestToRun>DistributedTest.Class1.TestOnAnotherMachine</TestToRun>
<Machine><your ip>:8080</Machine>
<TestParams>
<string>Hello World!</string>
</TestParams>

</TestConf>

</Tests>
</ParallelTest>
</ParallelTests>
</TestGroup>



PNUnit uses a older version of NUnit so use the same NUnit framework version that comes bundled with the PNUnit binary.

You need the PNUnit, .Net 2.0 or above framework and machines to be in the same network for the code to work. Provide for the appropriate ip and port number in the "pnunittests.conf" file.

Download PNUnit and extract the binary to a location. Compile and place the test assemblies(the test code posted above) in the same folder as PNUnit extracted files.

Open Command prompt, change directory to the PNUnit folder. Run "Start Agent agent.conf". The Agent window will open; next, Run "Launcher pnunittests.conf" file, the configuration file provided above.

For testing the "distributedtest.dll" on the remote machine, extract the "PNUnit" binary in that machine, place the .dll file into the same folder as in the local machine and start ONLY the agent in the remote machine. Run "Launcher pnunittests.conf" from the local machine. Default port used in agent.conf is 8080.

Happy Parallel Testing!

Thursday, 23 July 2009

ExpectedException - NotImplementedException

Recently, i got to thinking about how well suited the NotImplementedException is for Test-First approach of software development.

In Test-First or Test-Driven approach, you are required to write your tests first before writing any line of code.

For example, if you were to provide for a Calculator class, it is required that you write tests for the class first. But then, how do you write tests for a class whose operations do not exist? Simple. You test for the NotImplemented Exception!

There are many techniques available in NUnit. For instance, the Assert.Throws and .DoesNotThrow are good ways of asserting for an exception or you can simply use the [ExpectedException] attribute and decorate the test method so that the test knows that if NotImplementedException is thrown that is the right behavior of the test!

Below is a simple Hello World example demonstrating the usage of ExpectedException attribute alongwith the usage of the TestDelegate type in NUnit and writing to the Console (TextOutput pane) of the NUnit GUI.

using NUnit.Framework;
using System.Diagnostics;
using System;
namespace NUnit251_Tests
{
[TestFixture]
public class Class1
{
private WriteToNUnitConsole traceListener;
private SayHelloClass obj;
public class WriteToNUnitConsole:TraceListener
{
public override void Write(string message)
{
//throw new NotImplementedException();
Console.Write(message + "from NUnit");
}
public override void WriteLine(string message)
{
throw new NotImplementedException();
}
}
[SetUp]
public void InitTestData()
{
if (!Trace.Listeners.Contains(traceListener)){
traceListener=new WriteToNUnitConsole();
Trace.Listeners.Add(traceListener);
}
}
[TearDown]
public void DestroyTestData()
{
Trace.Listeners.Remove(traceListener);
}
[Test]
public void TestSayHelloWithWrite()
{
obj = new SayHelloClass();
Assert.DoesNotThrow(() => Trace.Write(obj.SayHello()));
}
[Test]
[ExpectedException("System.NotImplementedException")]
public void TestSayHelloWithWriteLine()
{
obj = new SayHelloClass();
obj.SayHelloThrowsException();
// Assert.Throws(typeof(NotImplementedException), (() => obj.SayHelloThrowsException()));
}

}
}

using System.Diagnostics;
namespace NUnit251_Tests
{
public class SayHelloClass
{
public string SayHello()
{
return "Hello World!";
}
public void SayHelloThrowsException()
{
//Trace.WriteLine("This method is not implemented");
throw new System.NotImplementedException();
}
}
}

As usual, i have commented out lines for you to try out different combinations.

This code has two tests - one commented and the other live. When both are uncommented, one test will pass and the other fail.

Happy TDD!

Saturday, 18 July 2009

Agile NCR Conference 2009

I presented on "ROI with Agile" and the session went much better than I had anticipated.

The conference, itself, was organized as well as last year and soon, we should probably see the NCR conference going international. Its popularity and enthusiasm generated by this conference is engaging and infectious.

My colleague, a first time attendee to the conference, was eager to check the budget of such a conference so tht our company could host it as well!

The organizers, Xebia, were gracious and the sponsors, Ericsson, were excellent in their support. The presentation by Hedwig Baars was excellent as was the participation of the Ericsson employees in the conference.

In all, a highly successful conference and after this conference, i genuinely believe that i, my colleagues at the conference and my company can go Agile, with total confidence.

Thursday, 2 July 2009

Generating test cases from an external class

The TestCaseSource attribute allows you to specify a method or a property, which could act as the source for your test cases. Simple and effective as TestCase attribute is TestCaseSource attribute is better.

A simpe rule that you must remember is that the class that contains a source method for the testCaseSource attribute must have a default constructor defined for it unlike the TestCase attribute.

// Class that uses another class' method as the source for its test method using the TestCaseSource attribute and taking the type and the name of the method as its arguments.

[TestFixture(21)]
public class TestCaseFromAnotherClass
{
private int expectedValue;
public TestCaseFromAnotherClass(int x)
{
expectedValue=x;
}
[Test,TestCaseSource(typeof(Enumerator_GeneratesData), "GenerateData")]
public void TestCaseSourceTest(int arg1, int arg2)
{
Assert.That(arg1*arg2,Is.EqualTo(expectedValue));
}
}

// Class that contains the source method for the TestCaseSource attribute and hence, must have a default constructor.

[TestFixture(42)]
public class Enumerator_GeneratesData
{
private int expectedAnswer;

public Enumerator_GeneratesData() { expectedAnswer = 42; }
public Enumerator_GeneratesData(int val) { expectedAnswer = val; }
public IEnumerable GenerateData()
{
for (int i = 1; i <= expectedAnswer; i++)
if (expectedAnswer % i == 0)
yield return new int[] { i, expectedAnswer / i };
}

//
[Test, TestCaseSource("GenerateData")]
public void TestGeneratedData(int x1, int y1)
{
Assert.That(x1 * y1, Is.EqualTo(expectedAnswer));
}

}

Monday, 29 June 2009

Type Inference - NUnit 2.5

//[TestFixture(12.0,42,TypeArgs=new Type[] {typeof(double),typeof(int)})]
[TestFixture("Hello", " World!",TypeArgs=new Type[] {typeof(string),typeof(string)})]
public class TestClass<targ,targ1>
{
private TArg val;
private TArg1 val1;
public TestClass(TArg val, TArg1 val1)
{
this.val = val;
this.val1 = val1;
}
//[TestCase(5.0, 7)]
[TestCase("Hello", " World!")]
public void TestTypesOfArgument(TArg t1, TArg1 t2)
{
Assert.That(val, Is.TypeOf<targ><targ>());
Assert.That(val1, Is.TypeOf<targ><targ>());
}}

Uncomment the commented lines and comment the other attribute to explore and know more!

Happy Testing of Types! :)

Friday, 19 June 2009

Product Development and Agile

Let us consider a product that has been released in the market and has won accolades for its UI. The next version, minor or major, of the product would obviously benefit from the appreciation but what if the product owners decide to tweak the UI more and settle for the menu’s look, feel and location.

Let us say that the below image represents the current menu look – the traditional drop-down menu. Imagine the plight of a designer who cannot see the changed look of his text.


And the below image is the proposed, new look for the same feature. This not only complies with the Mac and Windows Vista themes, it is also space saving that icons pop-up and reveal functionality as and when necessary and the menu itself can appear at the corners of the screen just like a rotating dial!

Great feature! So, what is the best way of developing this new feature?

There are many ways of developing software but the Agile way fits in on all counts due to its very nature of composition. Below are the reasons that the Agile way is a tailor-fit development method for products.

New Product/Feature plan and scope of Agile in it



Agile was formulated to suit scenarios where frequent or dynamic changes in requirements are present. And for a product’s lifecycle, these are the greatest impediments to the products’ success. Constant vigil on competition, growing technology and market demands make Agile the best suited way of software development for products.

There are lots of similarities in the nature and make-up of Agile teams and Product teams.

Both consist of talented, passionate and committed members. Both the teams are self-driven, self-motivated and innovative. Both teams are constantly looking for ways to improve the existing software towards “better software”.

The below table shows a comparison in the make-up of both the teams:

The best way, recommended, for UI implementations is to make sure that the designers and developers do a “Stand-up” meeting every day. This removes all ambiguities in what the designers envision and what the developers develop. The presence of QE (Quality Engineering) or QA, as is more popular called,  is also a great help as the scenarios become known to them and testing can happen in parallel.

Have a collaborative workspace.

Product development insists on innovation and creativity.

A collaborative workspace, where a team working on the same component/story when placed inside the same workspace will find better shared understanding and clarity than seated away in different cubicles or rooms.

Avoid cubicles, separate rooms and insist on a dining room kind of a layout with people sitting face to face on either side of the table.

Use LCD monitors that are compact and slim in shape; make sure the lighting is pleasant and well-ventilated.

The whole room is meant to be a complete workspace for the whole team and so have sufficient mediums of communications like a Video Conferencing facility, white boards, flip charts etc.

The stand-ups, video conferencing, telecoms and discussions are artifacts of an Agile method that increase the agility in the team and therefore, if you conduct all such meetings in separate places it would only lead to more loss of time, which will decrease the agility in the team.

Monday, 8 June 2009

The Agile "dryndrome"

When I used Procomm to develop (!) my first software in 1989 for Deccan Herald, a newspaper company based in Bangalore, it didn't seem to be a great activity. Of course, family members went ga-ga over my newly acquired skills and the amount of money that the effort brought in! In fact, I remember my father was almost glad that he had got back more than half the money he had spent in educating me and lavishly gifted me a good percentage of it!!

The approach was simple and I remember using a character from the character set to create a splash screen that evoked an envious "Hey, is this a Unix program?". In those days, anybody who programmed for Unix was considered to be a great techie!! The only time that I had a tryst with Unix was to use a dumb terminal to play PacMan!

I went into a non-IT profession, part-time, for about 3 years and returned to the IT industry in 1992 or thereabouts with my own company called "Semantix Computers". Looking back, even starting my own company did not mean a lot, as very few Airline companies, big institutions and travel agencies ( to impress their Airline friends) actually went for customized software development!

The first thing that comes to my mind when I cast my mind back to those days is the simplicity with which I used to work with the customers. The requirements were clear because the customer did not know what she wanted !! So, I had to patiently and correctly understand the requirements to the extent whether the customer wanted the print to be on a dot matrix printer or on a Laser Jet (the new swanky toy then!) printer!

If the software crashed, no worries! The customer could be told, "Please restart your machine!" and if the customer said, "I had forgotten to save my data. Does this mean that I cannot recover them now?" Not irate, not cursing! Just a simple query that would be met with, "Please remember to save frequently from now on" and you could actually chide the customer !!

Today, the same scenario possibly may exist in a rural village deep in Nagaland or in a pygmy country!

Requirements gathering, which has often been touted as possibly the most difficult of all phases of the SDLC, is missing just that one thing - the naive, trusting customer!! The customer, today, is far more educated than his predecessors as are the users and consequently, the definition of Quality, too, has changed. The growing competition in the market makes that revered Unix programmer almost a liability and a techie, who stresses on extensive documentation, a sure shot recipe for project failure. And, project failures across many studies have all identified, "Requirement changes" as the top reason for IT project failures with organizational and IT letdown as a close second.

This dread of requirements changing has possibly been the furore behind the Agile Development approach and the subsequent "dryndrome" that has emerged out of this race to become Agile!

A "dryndrome", it is, because of the dread that has driven its adoption.

Looking back to the early days of software development in India, I attribute the success of Agile methods to the increasing lack of clarity in the approach to software development. It is as simple as this; if you have not understood the requirements, it is natural to get this phase clear before going ahead with design or implementation!

There is no substitute for natural stupidity as there is no substitute for common sense. And since these are the essential elements in any sanity check list in a SDLC, that people are still failing despite have adopted Agile methods is a clear indicator that a method becomes madness if not understood correctly and not applied in the right context.

The number of interpretation that Agile methods have been subjected to is mind boggling! What has emerged for me to understand from my various interactions with the wannabe Agilistas or the wannabe Agile organizations is just this - if you do not have a first hand experience of the evolution of the IT industry in India then you will find it very difficult to truly understand what, why and how Agile is and, why it should be adopted and not implemented!!!

The "dryndrome" is likely to continue and the race for adopting Agile is likely to result in a few more newer Agile methods to satisfy the partially baked palates of the enthusiastic wannabes!

Monday, 25 May 2009

Wait Cursor for console

Creating your own cursor for a processing job is always interesting - no matter what the environment is. Below is the code for creating one for console on windows:

using System;
using System.Threading;
public class WaitCursor{
public static void DrawCursor(){
int y=0;
Console.SetCursorPosition(Console.CursorLeft+15,Console.CursorTop+15);
for (int i=0;i<10000;i++){>0)
y=Console.CursorLeft-1;
Console.SetCursorPosition(y,Console.CursorTop);
Thread.Sleep(500);
Console.Write("\\");
if (Console.CursorLeft>0)
y=Console.CursorLeft-1;
Console.SetCursorPosition(y,Console.CursorTop);
Thread.Sleep(500);
Console.Write(""); // Use the Pipe key when you download. Somehow the font does not seem to

//display it here.
if (Console.CursorLeft>0)
y=Console.CursorLeft-1;
Console.SetCursorPosition(y,Console.CursorTop);
Thread.Sleep(500);
Console.Write("/");
if (Console.CursorLeft>0)
y=Console.CursorLeft-1;
Console.SetCursorPosition(y,Console.CursorTop);
Thread.Sleep(500);
Console.Write("-");
if (Console.CursorLeft>0)
y=Console.CursorLeft-1;
Console.SetCursorPosition(y,Console.CursorTop);
Thread.Sleep(500);
Console.Write("\\");
if (Console.CursorLeft>0)
y=Console.CursorLeft-1;
Console.SetCursorPosition(y,Console.CursorTop);
Thread.Sleep(500);
Console.Write(""); // Use the Pipe key when you download. Somehow the font does not seem to

//display it here.
if (Console.CursorLeft>0)
y=Console.CursorLeft-1;
Console.SetCursorPosition(y,Console.CursorTop);
}
}
public static void Main(){
DrawCursor();
}}

There are further avenues to the above example.

Instead of a loop and a sleeping thread, an asynchronous operation could be used for the cursor's rendering.

You can also use a functional programming approach where the previous symbol (\-/-\) could act as the input for the DrawCursor() function!

Wednesday, 22 April 2009

Returning a "var" type from a method

The "var" type is a new introduction in .Net 3.x and it is also well known as an implicitly typed variable. The syntactical constraints are that they can be declared

1. Only inside a method.
2. only in a local scope.
3. only inside the scope of a method call.
4. only in an initialized state before being used.

So, if you require a "var" type returned from a method, you can do as below:

public class MyVar{
public static object VarReturningMethod(){
var implicitVar=new{LastName="Jv",
FirstName="Ravichandran"};
object nestedGenericVar = implicitVar;
return nestedGenericVar;
}
static void Main(){
var getVar=VarReturningMethod();
System.Console.WriteLine(getVar);}
}

Anonymous Types

Anonymous types are the most convenient way of working with those types, which do not need extensive usage or heavyweight creational structures.

The below code assigns a "var" type with a new instance whose type is/are the value(s) and their corresponding identifiers.

var implicitVar = new { Name = "A", Price = 3 };

So, if you do a

Console.WriteLine(implicitVar.ToString());

the output will be:

{Name="A", Price=3};

!!

The additonal advantage is that the variable "implicitVar" now knows the identifier's "Name" and "Price" as properties. So, you can do a:

implicitVar.Name and implictVar.Price

!!!

Extension Methods

An ExtensionMethod is a great technique introduced in .Net 3.x that extends on the existing capability of a type.

The syntax required by an Extension Method is that it should be static and cannot be created inside a non-generic static class. The method should consist of a parameter of that type for which this method is an extension of.

Syntactically, it means that the parameter should be prefixed with the "this" keyword followed by the type and identifier. For example, if you want to create an extension method for a type called "MyClass" then an extension method can be created in another class as below:

public static class MyExtendingClass{
public static void MyExtensionMethodForMyClass(this MyClass obj){
// Some statements
}
}

The below example extends the System.Int32 class and provides for an extension method called "IsInString". So, when a call to Convert.ToInt32() works on a string, the resultant integer will be provided with the newly created extension method as well.

using System;
namespace ExtensionMethodsExample
{
public static class ExtensionsClass
{
public static bool IsInString(this object o)
{
if (o is Int32)
{
int i = (int)o;
Console.WriteLine("Parameter passed is an integer type" + i);
}
if (o.Equals("24"))
return true;
return false;
}
}

public static void Main(){
Console.WriteLine((Convert.ToInt32("22") + Convert.ToInt32("2")).IsInString().ToString());

}
}

StructureMap and Dependency Injection

StructureMap is a new library that provides for a container to manage the lifetime of an object. Because the container is responsible for instantiating an object, it has to know the types that exist in a class/interface.

The StructureMap library provides for an ObjectFactory and a Container class that helps in initialising (extracting an instance) types like interfaces and other non-instantiable types.


Object Factory
The below code, for example, initializes the container and tells it that the default concrete type (which should be returned by the container to the caller) for a request for MyInterface type is "HelloWorldClass".


ObjectFactory.Initialize(x =>{x.ForRequestedType ()
.TheDefaultIsConcreteType(); });



The Lambda Expression, "x =>", helps in providing for inline execution logic. The "ObjectFactory" container, in the above code snippet, is initialized with knowledge on "RequestedType" and "ConcreteType".


In the below code snippet, "var" type variable is used to initialize types and set the default type as in the previous code snippet. The second statement, below, injects the property with the SetProperty method and using the "target" lambda expression specifies the value for the property.


var container = new Container(r =>{
r.ForRequestedType().TheDefault.Is.OfConcreteType(); r.ForConcreteType().Configure.SetProperty(target => { target.Hello = "Hello World"; });
});


The complete code is at the end of this post. You will require StructureMap library that can be downloaded at: http://sourceforge.net/project/showfiles.php?group_id=104740


The StructureMap architecture is as below:





Source: Sourceforge.net

Dependency Injection(DI)

DI is a happening subject doing the rounds and it has entered the .Net domain, too, with a bang.

Use DI to isolate one class from the actual implementation of its dependencies.

"Depend upon Abstractions. Do not depend upon concretions"

DI happens when the creation of a type is told to it through either parameters passed to constructor (Constructor Injection) or property (Setter Injection).

The below code is based on both Constructor Injection and Setter Injection. I have used the TDD approach to write the example, which also includes a mock object (Rhino Mock). You will need NUnit, StructureMap, Rhino Mock, .Net 3.5 to execute the below code.

Commented lines are different scenarios, which you can uncomment and explore.


using NUnit.Framework;
using Rhino.Mocks;
using StructureMap;
namespace StructureMapSimple
{
public class Proxy
{
private MyInterface obj;
public Proxy(MyInterface ob)
{
obj = ob;
}
public Proxy() { }
public string CallHelloMethod()
{
return obj.SayHello();
}
}
public interface MyInterface
{
string SayHello();
}
public class HelloWorldClass : StructureMapSimple.MyInterface
{
private string strHello;
public HelloWorldClass(string helloString)
{
strHello = helloString;
}
string MyInterface.SayHello()
{
return strHello;
}
public string Hello
{
get { return strHello; }
set { strHello = value; }
}
}
class Program
{
static void Main(string[] args)
{
}
}
[TestFixture]
public class TestClass{
private Proxy ob1;
[SetUp]
public void init()
{
//ObjectFactory.Initialize(x =>
//{
// x.ForRequestedType ()

// .TheDefaultIsConcreteType();
//});
ob1 = new Proxy();
}
[Test]
public void TestSetterInjection()
{
var container = new Container(r =>
{
r.ForRequestedType().TheDefault.Is
.OfConcreteType();
r.ForConcreteType().Configure
.SetProperty(target => { target.Hello = "Hello World"; });
});
Assert.AreEqual(container.GetInstance().Hello, "Hello");
}
[Test]
public void TestConstructorInjection()
{
var container1 = new Container(r =>
{
r.ForRequestedType().TheDefault.Is
.OfConcreteType();
r.ForConcreteType().Configure
.WithCtorArg("helloString").EqualTo("Hello");
});
Assert.AreEqual(container1.GetInstance().Hello, "Hello");
}
[Test]
[Explicit]
// [ExpectedException("System.InvalidOperationException")]
public void ShouldSayHelloWithRhinoMocks()
{
MockRepository mocks = new MockRepository();
MyInterface store = (MyInterface)mocks.StrictMock(typeof MyInterface));

// is equal to "(MyInterface) StructureMap.ObjectFactory.GetInstance(typeof(MyInterface)); "
ob1 = new Proxy(store);
MyInterface ob2 = (MyInterface)StructureMap.ObjectFactory.GetInstance (typeof(MyInterface));
//Expect.Call(ob1.CallHelloMethod()).Return("Hello World");
Expect.Call(ob2.SayHello()).Return("Hello World");
mocks.ReplayAll();
string s = ob1.CallHelloMethod();
//StructureMap.ObjectFactory.Inject(typeof(MyInterface), store);
Assert.AreEqual("Hello World", s);
mocks.VerifyAll();
}
}
}