About Me

Training

Nothin But .Net Developer Bootcamp

Navigation

Search

Categories

On this page

code.google.com/p/jpboodhoo!!!
ReSharper Templates
Huge Code Drop Coming!!!!!!!
Leveraging the EventHandler delegate more effectively
DateTime Formatting with single custom format specifiers
Nothin But .Net - New York , NY ( October 22nd - 26th, 2007 )
WPF - A New Set Of Shiny Tools (and the fastest way to get upto speed on it!!)
WPF/E - Get It While It's Hot
Fun With Linq and C# 3.0

Archive

Blogroll

 Agile Developer Venkat's Blog
 Ayende @ Blog
 B#
 Barry Gervin's Software Architecture Perspectives
 Boy Meets World
 Brad Abrams
 Canadian Developers
 Christopher Steen
 Claritude Software News
 Clemens Vasters: Enterprise Development and Alien Abductions
 Coding Horror
 Coding in an Igloo
 Dare Obasanjo aka Carnage4Life
 Darrell Norton's Blog [MVP]
 David Hayden [MVP C#]
 Don Box's Spoutlet
 Eric Gunnerson's C# Compendium
 EZWeb guy: Jeffrey Palermo [C# MVP]
 Fear and Loathing
 Generalities & Details: Adventures in the High-tech Underbelly
 Greg Young [MVP]
 Greg's Cool [Insert Clever Name] of the Day
 IanG on Tap
 Ingo Rammer's Weblog
 ISerializable - Roy Osherove's Blog
 James Kovacs' Weblog
 Jason Haley
 Jean-Luc David
 Jeremy D. Miller -- The Shade Tree Developer
 JetBrains .NET Tools Blog
 Jimmy Nilsson's weblog
 John Bristowe's Weblog
 John Papa [MVP C#]
 Jon Skeet's Coding Blog
 JonGalloway.ToString()
 Jump the Fence or Walk Around
 Lambda the Ultimate - Programming Languages Weblog
 Larkware News
 Lutz Roeder
 Marquee de Sells: Chris's insight outlet
 Martin Fowler's Bliki
 Mike Nichols - SonOfNun Technology
 MSDN Magazine - .NET Matters
 MSDN Magazine - All Articles
 OdeToCode Blogs
 Onion Blog
 Planet TW
 Raymond Lewallen [MVP]
 Rockford Lhotka
 RodMan's Corner
 Roger Johansson's blog
 Sahil Malik - blah.winsmarts.com
 Sam Gentile's Blog
 Scott Bellware [MVP]
 Scott Hanselman's Computer Zen
 ScottGu's Blog
 secretGeek
 Service Station, by Aaron Skonnard
 Signum sine tinnitu--by Guy Kawasaki
 Stephen Toub
 Steve Eichert's Blog
 Steven Rockarts
 The Blog Ride
 The Coding Hillbilly
 The Daily WTF
 TheServerSide.net: News
 Tim Gifford
 Vance Morrison's Weblog
 you've been HAACKED

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 369
This Year: 94
This Month: 11
This Week: 0
Comments: 973

 Wednesday, November 28, 2007
Wednesday, November 28, 2007 11:01:52 PM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | .Net 3.0 | Agile | C# | Continuous Integration | Patterns | Programming | Tools )

I finally set up a googlecode project to host source code for the various things I have been doing over the last year. The first major significant contribution is of course the code drop that I promised a week ago now!!

The application is the start of what I hope will evolve to be a great learning resource for lots of things related to .Net development. The application does not currently cover any of the “extra” topics that I did not have time to get covered in the course. This is perfect because as request come in from people (including past students) asking how to tackle a certain problem, I will use this application as the demonstration area where I can tackle the problem, and update the code base, and you will be able to update your local copy and carry on.

I am currently in the midst of a large Smart Client application that I am hoping to be able to harvest pieces of code out and do the exact same thing except for the smart client realm. I have much more experience developing in the smart client realm and that is where I feel most comfortable, so I am looking forward to be able to do another code drop (for a different application) in a couple of months.

I am going to write up another post about the Web Application as it is built very differently from traditional .Net based web applications. In following with the theme for my courses, there are currently no 3rd party frameworks (other than log4net) that have come into play. My goal with this web app is to demonstrate to people how far we can push raw .Net. The goal being that expanding their knowledge of how to creatively leverage .Net, they will be better prepared to jump into frameworks that they may currently feel daunted by. As time goes by, I will swap pieces of the application out with components that people are asking to see meaningful samples on:

  • NHibernate
  • Castle
  • Prototype
  • JQuery
  • ..*

As the app stands right now I see it as the beginning of what will shape up to be a pretty mean machine!!

I am going to post a screencast that will show people how to get started working with the web application. For people who are eager to get going right now, here are the quick and simple steps without a lot of explanation (that will come in the next post):

  • Anonymously checkout the trunk from the google code repository using the following svn command line:
    svn checkout http://jpboodhoo.googlecode.com/svn/trunk/ jpboodhoo-read-only
  • Navigate to the checkout folder
  • Go into the build folder
  • Copy local.properties.xml.template and paste it into the same directory, then rename the copied file to local.properties.xml
  • Open up the local.properties.xml file with your favourite text editor.
  • Modify any of the settings in the file that are different on your machine.
  • Open up a command prompt and navigate to the build directory of the code.
  • type: build load.data and hit enter.
  • type: build test.all.woc
  • type: build run
  • The last task should fail (I haven’t automated everything yet)
  • Create a virtual directory called nothinbutdotnetstore that points at the following location (this location is created after you attempt to run the build run task) : ${checkoutfolder)\build\deploy\web\app
  • After successfully creating the virtual directory try the build run task again.
  • If the web browser pops up pointed at a web page (for the app) you are in business. Feel free to click through the first set of pages that are implemented (only 3 pages are currently implemented).

As far as what I have planned to implement in the web app (that is currently not implemented):

  • Build out a more extensive domain model that encompasses some more advanced scenarios of the application (especially around order processing).
  • Unit Of Work for the service layer
  • Implement a lightweight OR/M layer
  • Integrate some UI frameworks like prototype
  • Eliminate Master Pages completely and switch to a much more elegant template view pattern.
  • Introduce a more robust container (as the current one is a simple dictionary wired up in a simple procedural fashion).
  • Introduce the concepts of lifecycles for the items in the container. Right now, everything wired into the container is essentially a singleton.
  • Introduce CSS based layout for the web pages (working with a designer on this one).
  • Bring security concerns into play
  • Demonstrate how to effectively manage sessions
  • ……lots,lots,lots more!!!

Obviously I will be leaning on people checking out the code and playing around with it and submitting requests for things they would like to see.

There are a couple of things that you will immediately notice about the application:

  • Clean front controller implementation with ASPX pages as the template views. There are no code behind pages in this web application. All web requests are handled by command objects that interact with the service layer, push the details into a “ViewBag” and then choose which view to render.
  • Logical layers in the project are separated using simple folders and namespaces (not full blown projects)
  • Build automation is its own project in the solution (props to Jay Flowers for this inspiration)
  • The current container implements (CustomDependencyContainer) is very simple and is handled by a big procedural application startup task.
  • Compile time support for the database layer. A couple of classes ago I introduced the concept of a generic TableColumn<T> type. In England after introducing this concept Scott Cowan leveraged his knowledge of MyGeneration to automatically generate strongly typed table definitions that we could leverage to do mapping (trust me when I say, this is nothing like datasets). Until moving into OR/M concepts deeper this gives a good place to start as the generation of the TableDefinitions is linked to whenever the SQL files change, so you will get compile errors if column types are now mismatched etc…

There are lots of other things I could talk about, but this code really is the start of what I see being a long running conversation between myself and other people wanting to learn. In all honesty for all of the emails I have not paid attention to this year, hosting code through google will allow me to answer peoples questions in a much more meaningful way as I can point them at this site to see the implementation of the code they had questions about.

I am going to be placing all of the code for presentations that I have done for the last year as well as continue to update it with the source code that comes out of new courses that will be coming out in the new year, and the DNRTv episodes.

Once again, the application is currently in its infancy, but as people start sending in the requests I now will have a venue and example to add upon to answer questions in a much more timely fashion!!!

 

Develop With Passion!!!

 

 

Comments [6] | | # 
 Tuesday, November 13, 2007
Tuesday, November 13, 2007 1:55:06 PM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | .Net 3.0 | C# | General | Tools )

Since I have been asked for these quite a few times, I thought I would oblige and give these out. You can find below the links for both my Resharper Live Templates and File templates.

Enjoy:

Comments [1] | | # 
 Sunday, November 11, 2007
Sunday, November 11, 2007 5:48:00 AM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | .Net 3.0 | Agile | C# | Programming | Training )

A lot of people will probably say it is about time!! I am taking the source code that just got driven out from this last week of Nothin But .Net and I am going to make it publicly available from my blog. I am hoping to release it by the end of the week. The reason that I can’t release it yet, is that there are lots of concepts that I wanted to cover in class that I did not have time too, so I am going to spend a bit of time fleshing out the code base to include all of the concepts that were missed (by student request)

Keep in mind that Nothin But .Net is a course about fundamental software development practices with a bit of a .Net slant. Here are some of the things you will be able to see in the code base:

  • How Test Driven Development was used to drive out the functionality of screens in the application in a top down fashion
  • The benefit of using Data Transfer objects not as a marshaling tool, but as a tool to let the needs of the UI not influence unecessary changes to the domain model
  • The benefits of leveraging layered architecture
  • Why you don’t need lots of projects in your enterprise solutions if you are using an automated build (take  a look at the following screenshot to get an idea for the solution structure
  • Clean Front Controller implementation so that you can eliminate the need for messy Passive View/Supervising Controller implementations just for testability of the web form world
  • Good practices around mixing both interaction and state based testing
  • Test partitioning (integration, unit, acceptance)
  • My current project build structure
  • How to avoid the overspecification problem with interaction based testing
  • Rhino Mocks and leveraging the automocking container (thanks James for getting me hooked on this thing)
  • Fluent Interfaces
  • Build Automation
    • NAnt compilation as an effective tool for pruning dead code that studio does not show
    • NAnt as a build tool
    • NAnt as your compiler and test runner
    • Build file partitioning
      • Use of filesets
    • Machine agnostic build files through use of local property files
  • Unit Testing
    • Focusing on one thing at a time
    • Incremental testing
    • Breaking reliance on setup methods
  • MBUnit
    • Decorators used effectively
  • Design Patterns
    • Visitor
    • Factory
    • Data Transfer Object
    • Adapter
    • Proxy
    • Mapper
    • Unit Of Work (lots of people have been bugging me about this for a while)
    • Lazy Loading
    • IOC
    • Gateway (and Static Gateway)
    • Service Layer
    • Identity Map
    • Data Mapper
    • Database Gateway
    • Money
    • Null Object
    • Strategy
    • Composite
    • Command
    • Template View
    • Query Object
    • Specification
    • Domain Model
    • Separated Interface
  • Design Principles
    • Single Responsibility
    • Open Closed principle
    • Dependency Inversion Principle
    • Hollywood principle
    • Tell Don’t Ask

I am sure I am missing lots in the description above, but you get the general idea. The important thing to note, is that all of the code (except for the changes I am making this week) was driven out through the course of the one week bootcamp!!

I am going to spend a couple of days ensuring that it contains as much code as possible for an initial drop, with full end to end functionality in place.

Going forward, this code will serve as a good place for me to be able to demonstrate in a public arena, concepts that people email me and ask me questions about. This way, I won’t have to spend as much time blogging, people can send me a question about something they are having problems with, I can implement the solution in the codebase and they can see how I attacked the problem from a test first perspective.

I envision this as being a very organic application. I am going to use it as a public tool to share whatever knowledge I have with as many people as possible.

When I post the code I will make sure I post a little about the application and why I feel that it will serve as a good tool to both teach and practice.

Comments [8] | | # 
 Wednesday, July 11, 2007
Wednesday, July 11, 2007 7:29:16 AM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | .Net 3.0 | C# )

If you are now coding in .Net 2.0/3.0/3.5 and are creating types that expose events. Chances are you have started leveraging the EventHandler<T> delegate that frees you from creating custom delegate signatures for events anymore. If not this post is for you. Let’s say that you want to expose an event that another object could consume. Normally you would follow these steps:

  1. Create a type that inherits from EventArgs if the event is going to propagate event specific data. This step is optional as you may not have any custom data to propagate.
  2. Create a delegate signature for the event. If you are not using a custom EventArgs derivative, then you can get away with just leveraging the EventHandler delegate that already exists in the framework.
  3. Create the type that is going to raise the event and have it declare the event using either implicit or explicit event registration.
  4. Create a method on the type that will raise the event.

In .Net 2.0/3.0/3.5 these steps can now become:

  1. Create a type that inherits from EventArgs if the event is going to propagate event specific data. This step is optional as you may not have any custom data to propagate.
  2. Create the type that is going to raise the event and have it declare the event using either the EventHandler delegate type for an event that does not propagate custom data, or leverage the generic EventHandler<T> delegate to declare an event bound to the specific EventArgs derivative you need to use. Again you can use either implicit or explicit event registration.
  3. Create a method on the type that will raise the event.

This can actually become slightly better. Instead of always creating a class that derives from EventArgs if you need to pass custom data; create a parameter object that encapsulates the information you would want to propagate in the event. This class does not need to inherit from EventArgs. Then create the following utility class:

 

public class EventArgs<T> : EventArgs { private T eventData; public EventArgs(T eventData) { this.eventData = eventData; } public T EventData { get { return eventData; } } }

This means that the 3 steps above can now be changed to:

  1. Create a parameter object that encapsulates any information you want to propagate in the event.. This step is optional as you may not have any custom data to propagate.
  2. Create the type that is going to raise the event and have it declare the event using either the EventHandler delegate type for an event that does not propagate custom data, or leverage the generic EventHandler<T> delegate, with the generic EventArgs<T> class to declare an event bound to the specific parameter object you need to use. Again you can use either implicit or explicit event registration.
  3. Create a method on the type that will raise the event.

 

So if I had a parameter object that looked like this:

public class ReportingPeriod { private DateTime start; private DateTime end; public DateTime Start { get { return start; } } public ReportingPeriod(DateTime start, DateTime end) { this.start = start; this.end = end; } }

I would be able to create a type that raises an event to propagate this data as follows (using implicit registration):

public class ReportTrigger { public event EventHandler<EventArgs<ReportingPeriod>> RunReport; }

Or using explicit registration:

public class ReportTrigger { private EventHandler<EventArgs<ReportingPeriod>> subscribers; public event EventHandler<EventArgs<ReportingPeriod>> RunReport { add { subscribers += value; } remove { subscribers -= value; } } }

Develop With Passion!

Comments [3] | | # 
 Tuesday, July 10, 2007
Tuesday, July 10, 2007 6:04:13 PM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | .Net 3.0 | C# )

I may be the last one in the .Net world to find this one out!! Say you wanted to execute the following string format statement:

 

return string.Format("{0:MMMM} {0:d}-{1:d}, {0:yyy}", start, end);

The result of that format command would be: January 1/1/2007-1/7/2007, 2007. This is obviously not what I was expecting. In order to specify a single character format specifier I have to use the following:

 return string.Format("{0:MMMM} {0:%d}-{1:%d}, {0:yyy}", start, end);

Which results in the following output: January 1–7, 2007 (which is what I wanted).

Notice the use of the % format specifier prior to the single digit day format specifier. That is what I was missing. If you want to know more about how this works check out the documentation here.

Develop with passion!

Comments [0] | | # 
 Monday, June 25, 2007
Monday, June 25, 2007 3:52:19 PM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | .Net 3.0 | Agile | C# | Patterns | Programming | Training )

That’s right folks. Nothin But .Net is coming to New York.

The course is going to be held at TCCIT Solutions.

 The course runs for the week of October 22nd – 26th, 2007.

Overview

Nothin But .Net is a five day boot camp that will focus on pragmatically applying .Net within the context of developing a working N-Tiered application. Registrants will learn about advanced features of .Net (2.0/3.0) as they are applied to the task of building a complete application from the UI layer all the way down to the mapping layer.

WARNING!!!!

If you are expecting to come to this course to learn about how to have VS.Net automatically generate an “application” for you, then this course is NOT for you.

This course is all about taking control of the .Net framework and having it work the way you want. This course will place a heavy emphasis on getting back to the basics and making .Net do things the way you want it to, in a predictable and testable way.

This course will focus on a code centric view of application development vs. the typical databinding/designer magic covered by many typical .Net courses. You will walk away with a deep understanding of fundamental aspects of .Net and how these pieces can be used to develop and deliver enterprise scale applications.

Core Concepts Overview

  • Expanding the capabilities of developing with VS.Net - Enter ReSharper (a productivity add-in for Visual Studio .Net)
  • There’s more to life than generated code
  • Automation for the developer
  • Generics ( they’re not just for collections )
  • Back to basics - Rules Of Good Object Oriented Design
  • Dependency Injection
  • Object Relational Mapping in .Net
  • Applying the dependency inversion principle
  • Domain Driven Design
  • Passive View/Supervising Controller (Model View Presenter)
  • Creating layered architectures
  • Driving out functionality and design through testing
  • Taking Control Of Databinding
  • Behavior (Test) Driven Development
  • Core design patterns applied
  • Pragmatic Productivity Tools For Developers

Although the list may look rather daunting, the majority of the bullet points will be covered during the evolutionary design and construction of the sample project.

One of the main goals of the course is to show how to effectively use behavior (test) driven development, design patterns and a solid toolset to develop a portion of a non-trivial application.

The course will allow students to pragmatically apply BDD practices as well as teach people how to utilize fundamental OO concepts and techniques that will allow for them to have cleaner, more loosely coupled architectures. It will also be an opportunity for students to see what is involved in creating applications that utilize a Rich Domain Model,and the supporting infrastructure that is required to use "Plain Old Objects".

I have successfully delivered this course several times with great success. I anticipate that people who are interested will find that this is a very unique course offering, not typical of what is being delivered in the mainstream.

Seats are limited. The course costs $3000/US for a full 5 days. The fee covers:

  • 5 (8 - 14 hour days, depending on the audience availability) of bootcamp style instruction
  • Breakfast
  • Hot Lunch
  • Book - Patterns Of Application Architecture
  • Software – ReSharper 3.0 License

If you have any questions please don't hesitate to contact me at jp@jpboodhoo.com.

To Register for the course please use the following link:

Comments [2] | | # 
 Tuesday, April 10, 2007
Tuesday, April 10, 2007 7:33:37 AM (Mountain Standard Time, UTC-07:00) ( .Net 3.0 )

For those of you who have not started looking into WPF, time to start!! Even if you don’t care about the flash and jazz of the UI bits, there are pieces in there that you might want to think about leveraging in your own applications right now. One of the things that is immediately apparent to me is the evident design work that went into the development of WPF. Some of the things I have had a chance to play with that have stuck me are:

  • Logical and Visual Trees
  • Dependency Properties
  • Routed Events
  • ICommand interface (finally I can stop rolling my own!!)
  • First class command pattern support for common UI widgets
  • Even though I am not a fan of databinding, some of the enhancements that have been brought to the table are pretty impressive:
    • CompositeCollections
    • MultiBindings
    • PriorityBindings (again, finally I can stop rolling my own!!)
  • ValidationRules and ValidationResults (again,.. you get the point)!!
  • Retained-mode graphics system!!
  • Animation

I could carry on, but I think you get the point. As a developer who errs to the side of writing custom explicit code to make the UI more maintainable, WPF brings to the table a host of features that I can leverage to mix the declarative nature of XAML, with the explicitness of writing clean well-factored code that leverages proper separation of responsibilities while also taking advantage of not needing to hand roll so much stuff that I had to do with prior versions of .Net.

If you want to get upto speed quickly on what WPF can do for you, I recommend rushing to pick up a copy of the book Windows Presentation Foundation Unleashed by Adam Nathan. The book is an awesome read, and it gives you a solid grounding in all of the root concepts that you need to GROK to utilize WPF in a practical fashion.

 

Comments [3] | | # 
 Tuesday, December 05, 2006
Tuesday, December 05, 2006 8:33:35 AM (Mountain Standard Time, UTC-07:00) ( .Net 3.0 )

Scott Guthrie just announced on his blog the public community preview of WPF/E.

If they are pitching this as a flash killer, then from first impressions (given the fact that it runs on Firefox, IE, and Safari) I would say they have taken an incredible step in the right direction.

Install it and play around with the samples. Make sure to check out the demos listed on Scott's blog.

On my machine (Windows Vista) installing the SDK did not allow me to run the samples, so I also installed the CTP of the runtime which can be found here.

Enjoy.

Comments [2] | | # 
 Thursday, December 15, 2005
Thursday, December 15, 2005 8:36:03 AM (Mountain Standard Time, UTC-07:00) ( .Net 3.0 | C# )
As you already may know, Microsoft released the preview of Linq a while ago, to give developers a chance to play with some of the language features that are going to be in C# 3.0. Some of the new features that will be introduced are:

  • Extension Classes
  • Lambda Expressions
  • Language Integrated Query(LINQ)


So what does all this mean to you as a developer? Here is an example of what can be accomplished with extension classes. How many times have you found yourself writing some sort of StringUtility class in your applications? Would'nt it be nice if you could just add methods that all instances of string would be able to call? Well with C# 3.0 it looks like this:


1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Query;
5 using System.Xml.XLinq;
6 using System.Data.DLinq;
7 using NUnit.Framework;
8 using LinqMadness.Core;
9 using System.Query;
10 namespace LinqMadness.Test
11 {
12 [TestFixture]
13 public class StringExtensionTest
14 {
15 [Test]
16 public void ShouldBeAbleToReverseString()
17 {
18 Assert.AreEqual("tsaoT","Toast".Reverse());
19 }
20
21 [Test]
22 public void ShouldBeAbleToTestForPalindrome()
23 {
24 Assert.IsTrue("pop".IsPalindrome());
25 Assert.IsTrue("barcrab".IsPalindrome());
26 Assert.IsTrue("elbertandednatreble".IsPalindrome());
27 Assert.IsFalse("nonPalindrome".IsPalindrome());
28 }
29
30
31 }
32 }
As you can see from the above test class, using extension classes I have been able to dynamically add methods to any instance of a string object. How did he do that?? Look at the following code that shows how this is accomplished:

1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Query;
5 using System.Xml.XLinq;
6 using System.Data.DLinq;
7 8 namespace LinqMadness.Core
9 {
10 public static class StringExtensions
11 {
12 public static string Reverse(this string stringToReverse)
13 {
14 StringBuilder builder = new StringBuilder(stringToReverse.Length);
15 for(int i = stringToReverse.Length-1;i>=0;i--)
16 {
17 builder.Append(stringToReverse[i]);
18 }
19 return builder.ToString();
20 }
21
22 public static bool IsPalindrome(this string toCheck)
23 {
24 25 for(int i = 0;i < toCheck.Length/2;i++)
26 {
27 if (toCheck[i] != toCheck[toCheck.Length -1 -i])
28 {
29 return false;
30 }
31 return true;
32 }
33 34 }
35 }



A couple of key points to note here. Notice the use of a static class. More importantly look at the signature of one of the methods that extends string with new functionality:

public static string Reverse(this string stringToReverse)

The use of the this keyword coupled with the type argument to the method indicates that this method is a behaviour that now will belong to all string instances.

Ok, so as cool as that is, take a look at the following code that demonstrates some of the new LINQ features in C# 3.0.


1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using NUnit.Framework;
5 using System.Query;
6
7 namespace LinqMadness.Test
8 {
9 [TestFixture]
10 public class CollectionTest
11 {
12 [Test]
13 public void ShouldBeAbleToFindAllOddNumbersInList()
14 {
15 List<int> numbers = new List<int>();
16 numbers.Add(1);
17 numbers.Add(2);
18 numbers.Add(3);
19 numbers.Add(4);
20 numbers.Add(5);
21
22 Assert.AreEqual(3,numbers.FindAll(i => (i % 2) != 0).Count);
23 Assert.AreEqual(1,numbers.Min());
24 }
25
26 [Test]
27 public void ShouldBeAbleToCreateCustomType()
28 {
29 IList<Customer> customers = new List<Customer>(){newCustomer("JP","555-4444",23,"SomeAddress","Canada"),
30 new Customer("Aaron","555-4444",23,"SomeAddress","Canada")};
31
32 foreach (Customer customer in customers)
33 {
34 var customerDTO = new{customer.CustomerName, customer.Phone};
35 Assert.AreEqual(customer.CustomerName,customerDTO.CustomerName);
36 Assert.AreEqual(customer.Phone,customerDTO.Phone);
37 }
38 }
39
40 [Test]
41 public void ShouldBeAbleToUseQuerySyntax()
42 {
43 IList<Customer> customers = new List<Customer>(){new Customer("JP","555-4444",27,"SomeAddress","Canada"),
44 new Customer("APerson1","555-4444",27,"SomeAddress","Canada"),
45 new Customer("APerson2","555-4444",8,"SomeAddress","Canada"),
46 new Customer("APerson3","555-4444",6,"SomeAddress","Canada"),
47 new Customer("APerson4","555-4444",3,"SomeAddress","Canada"),
48 new Customer("APerson5","555-4444",1,"SomeAddress","Canada")};
49
50
51 IEnumerable<Customer> customersOver8 = from c in customers
52 where c.Age > 8
53 select c;
54
55 IEnumerable<Customer> customersBeginningWithA =