In addition to my first post about the new .NET 3.5 language features my second post in this series will be about Lambda Expressions. Lambda Expressions are basically a follow up to Anonymous Methods (in-line delegates), which were introduced in .NET 2.0. The advantage of Lambda Expressions over anonymous methods is that it is a superset of anonymous methods (more functionality) and that it provides a more concise, functional syntax for writing Anonymous Methods (C# 3.0 specification).
Based on the example of my Extension Methods post a foreach method, which takes a generic Action delegate as a parameter, can be created with an anonymous method. To invoke the SaySomething method for every Person object in the list you can write:
_persons.ForEach(delegate(Person p)
{
p.SaySomething("Hello");
}
);
Using the Lambda Expression syntax this same code will be:
_persons.ForEach(
p => p.SaySomething("Hello")
);
The syntax of param => expression is not only shorter and easier to read (once you are used to it), it is also implicitly typed. The type of p is inferred by the compiler and IntelliSense as a Person object, which is possible because the ForEach method is executed on a list of Person objects. The parameter p can also be explicitly typed by using the syntax (Person p) => p.Say...().
In this case, where the Lambda Expression takes one parameter and doesn't have a return value, the definition of the method is with a parameter of the generic delegate type Action<T>. So in case you want to write a method, e.g. as an IList extension, that takes these kind of Lambda Expressions you can write:
public static void MyForEach<T>(this IList<T> list, Action<T> doFunc)
This method can be invoked exactly the same as the normal ForEach method, with either a delegate or a Lambda Expression. Of course a lot of other great constructions are possible, for example a DoIfMatch method that executes an action when there is a match found. Note that for the match function you use the generic delegate Func<T, R>, where T is the type of the input parameter and R is the type of the result:
public static void DoIfMatch<T>(this IList<T> list, Func<T, bool> matchFunc, Action<T> doFunc)
This method can be called using:
_persons.DoIfMatch(
p => p.Name == "Person II",
p => p.SaySomething("Hello")
);
In relation to LINQ Lambda Expressions are used in the Where-part and the OrderBy-part. There is a distinction however in LINQ implementations based on IEnumerable and IQueryable. The first one uses the Func<T, R> delegates as explained above. The latter one however uses the Expression<Func<T, R>>, which makes evaluation of the Lambda Expression possible. This way LINQ to SQL, for example, can add the where part in de SQL query before it is send to the database. The Lambda Expression that you use in both cases aren't any different though.
The source code can be downloaded from here: LambdaExpressionsDemo.zip (,87 KB)
When opening my blog today I received an error message indicating that the WPF/E (Silverlight) version installed on my system is out of date. The result of the error is that my post about Silverlight isn't working anymore (in fact, the area of the app is not refreshed and shows bits and pieces of other content on the page). The new 1.0 RC (javascript) and 1.1 Alpha Refresh (javascript and managed code) versions can be downloaded from here. However, that doesn't help with my example, although the 'Get Microsoft Silverlight' image is back. The key to get it working again is to update the project with the new 'Silverlight Tools Alpha Refresh for Visual Studio', which is for VS2008 Beta II. But than I ran into error 'AG_E_INVALID_ARGUMENT 2210 Error' when the app tried to load my button (which is in another assembly). To solve this problem you have to make sure that the build action of the XAML control is set as 'Embedded Resource', which is described in a blog post of Rob Conery. So the browser requires you to upgrade the client machine, but the software isn't backwards compatible. I guess you shouldn't write software with beta's if you don't want this to happen...
The new beta of Visual Studio 2008 and the .NET Framework 3.5 is just released and can be downloaded from http://msdn2.microsoft.com/en-us/vstudio/aa700831.aspx. Most important for this release is that it includes a Go-Live license, which means that you can officially use this version in a production environment. I don't know exactly what other differences there are compared to beta 1 but I saw something about Partial Methods. It is downloading now, but that will take a while I'm afraid... BTW. Official release is planned for February 27, 2008 (also the date for SQL Server and Windows Server 2008).
This is the first post in a series of xx that will be about the preparation of a presentation for my HintTech colleagues, 'LINQ and the related new features of .NET 3.5'. Today I start with the feature Extension Methods.
In the C# 3.0 Specification Extension Methods is defined as 'static methods that can be invoked using instance method syntax, which make it possible to extend existing types and constructed types with additional methods'. In a simple example of a Person class that has a Name property, you might define an Extension Method using the following syntax:
namespace ExtensionMethodDemo.Domain.Extensions
{
public static class PersonExtensions
{
public static void SayGoodbye(this Person person)
{
Console.WriteLine(person.Name + " : Goodbye");
}
}
}
Note that both the class and the method are declared as static and that the (first) parameter is defined as 'this Person person', which defines the type to which the extension method applies. When you invoke this method 'the difficult' way:
ExtensionMethodDemo.Domain.Extensions.PersonExtensions.SayGoodbye(person);
there is basically nothing new to Extension Methods. Leave out the 'this' in the parameter and you can do the same in .NET 1.0, 1.1 and 2.0. As with normal static methods, Extension Methods also have the same limitations, ie. you only have access to the public's of the Person class.
One of the powers of Extension Methods is that (after you import the namespace) the extended method appears as an instance method, so you can invoke it directly on the instance of a class:
It even appears in the IntelliSense, with an indication that it is an extension to the original class. Taking into account that Extension Methods can also be applied on all .NET Framework classes (including object, string, etc.), you can imagine that some really powerful stuff is possible. For example you might have a look at the In() example of Scott Guthrie, which is an extension method to object.
Besides using Extension Methods on existing classes it is also possible to create shared interface implementations. Using this you can implement a general part of an interface using Extension Methods, which can avoid duplicate code in classes that implement the interface while clients have access to all the methods.
In the example below an interface is defined that is extended by a shared interface implementation. Doing this the Person class only has to implement SaySomething and clients have access to both methods SaySomething and SayHello through the interface IPerson:
public interface IPerson
{
void SaySomething(string text);
}
namespace ExtensionMethodDemo.Domain.Extensions
{
public static class PersonExtensions
{
public static void SayHello(this IPerson person)
{
person.SaySomething("Hello");
}
}
}
In relation to LINQ the feature of Extension Methods is used for the extensions on IEnumerable<T> and IQueryable<T>, for example the Where() method. The advantage of implementing this as Extension Methods is that you only have the methods in scope when you use LINQ, not when you just need the interface.
The source code can be downloaded from here: ExtensionMethodSample.zip (,57 KB)
This blog post is about how to develop a small Silverlight (the new MS plug-in for Rich Interactive Applications (RIAs) on the web) application and get it running inside this post. The demo app is quite simple, it has a button that pop ups the Silverlight logo when it is pushed. Install development environment For development of Silverlight apps the Orcas edition of VS is required plus some additional Silverlight packages, which can be downloaded from the Silverlight web site: the runtime 1.1 alpha, development tools for VS Orcas and the SDK for the necessary documentation and samples. Using one of the Expression designer tools is optional but if you want to some fancy design stuff a designer is really a must. For this project I used Expression Blend 2 May Preview as the older version doesn't support Silverlight. Design with Expression Blend To get to know a bit about Silverlight and the graphical design possibilities using Expression Blend I used the great tutorials of nibbles tutorials. Playing with these tutorials gives you a great insight in using Blend to create graphical assets and use them in you app. For this applications I've created the round button as a user control in a separate assembly. By adding some animations the button changes color when the mouse enters, and transforms a little smaller when you click it to create a button down effect. The rest of the app, including an animation to pop up the picture, is designed on the page.xaml, which is generated when you create a Silverlight app in Visual Studio. To use the button (from the separate assembly) on the page you have to define a namespace in the main canvas of the page.xaml to include the dll: <Canvas xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myctrl="clr-namespace:SilverlightDemoClasslib;
assembly=ClientBin/SilverlightDemoClasslib.dll"
...
>
Now you can add the button by including the namespace prefix:
<Canvas x:Name="buttonCanvas" Canvas.Left="15" Canvas.Top="55">
<myctrl:SilverPlayButton x:Name="PlayButton"></myctrl:SilverPlayButton>
</Canvas>
Unfortunately there is a little problem now, the page.xaml doesn't open in Blend anymore because it cannot find the button. At this moment I don't know how to fix this yet. I worked around it by adding the button at the last moment, when I didn't need Blend anymore.
Animations and Events
The timelines that were recorded in Blend (see the XAML file) have to be connected to the mouse events of the Canvas object. The MouseEnter and MouseLeave events are left out of the code below because it is pretty much the same.
public class SilverPlayButton : Control
{
private FrameworkElement implementationRoot;
private Canvas _button;
private Storyboard _mouseDown;
public SilverPlayButton()
{
System.IO.Stream s = this.GetType().Assembly
.GetManifestResourceStream("SilverlightDemoClasslib.SilverPlayButton.xaml");
implementationRoot = this.InitializeFromXaml(new System.IO.StreamReader(s).ReadToEnd());
// Assign private variables
_button = implementationRoot.FindName("button") as Canvas;
_mouseDown = implementationRoot.FindName("mouseDown") as Storyboard;
// Add eventhandlers
_button.MouseLeftButtonDown += new System.Windows.Input
.MouseEventHandler(_arcButton_MouseLeftButtonDown);
}
void _arcButton_MouseLeftButtonDown(object sender, System.Windows.Input.MouseEventArgs e)
{
// Start animation
this._mouseDown.Begin();
}
}
The last thing to do is to add an eventhandler for the button click in the page.xaml to start the animation of the picture.
public partial class Page : Canvas
{
public void Page_Loaded(object o, EventArgs e)
{
InitializeComponent();
PlayButton.MouseLeftButtonDown += new MouseEventHandler(PlayButton_MouseLeftButtonDown);
}
void PlayButton_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
popupImageAnimation.Begin();
}
}
Running Silverlight in dasBlog
That is not a real problem because, from a server point of view, Silverlight is just a bunch of javascript code. To get it running you copy the ClientBin folder (including the dll's), page.xaml file and the javascript files (Silverlight.js and TestPage.html.js) to the root of your web folder. However, because I didn't want the root of my web server to be filled with these kind of files I created a separate ClientScripts folder for the xaml and js files. When you do so you have to make a change in the TestPage.html.js, which has a reference to the page.xaml:
function createSilverlight()
{
Sys.Silverlight.createObjectEx({
source: "ClientScripts/Page.xaml",
...
}
Now you can add a div to your blog post that acts as the host of the Silverlight app (note that you add the path to the js files):
<script src="ClientScripts/Silverlight.js" type="text/javascript">
</script>
<script src="ClientScripts/TestPage.html.js" type="text/javascript">
</script>
<div id="SilverlightControlHost">
<script type="text/javascript">createSilverlight();</script>
</div>
And it should work...
Update: Removed the demo from this post because it doesn't work anymore with the new SL versions.
Last week was the biggest Microsoft developer event in the Netherlands, the DevDays 2007. It was a two day event with a lot of sessions (50+) presented by some of the greatest names in the world of software development like Scott Guthrie, Dino Esposito and Ingo Rammer, to only name a few. Together with this event there was also the ReMIX, which added another 15+ sessions. Unfortunately it was only possible to follow 9 of the sessions plus the keynote, making it very hard to choose... One of the biggest things during this event was the presentation of Silverlight, the cross-browser and cross-platform .NET plug-in for Rich Interactive Applications (RIAs) on the web. Scott Guthrie presented it during the keynote and in two full sessions on the second day, explaining what is in it now and what is planned for the near future. What I've seen from Silverlight (former WPF/E) until now is really incredible! Especially the demo of the project TopBanana, a video editing tool from Metaliq.com entirely built with Silverlight. At this moment Silverlight is at the 1.0 beta / 1.1 alpha stage and is cross-browser and cross-platform only for Windows and Mac, a version for Linux is planned by the Mono project. According to Scott it is not recommended to start a business project with Silverlight at this moment however. You'll be missing a lot of controls that you might expect out-of-the-box but which are just not in yet. They will definitely be included though with next releases later this year. Another main thing of the event where the topics surrounding the .NET Framework 3.0. Many very interesting sessions covered the various aspects around WPF, WCF and WF. The demonstration of the air-hockey game by Mark Miller was real fun. He build this game where two instances of the application can connect with each other using WCF to play. The user interface of the application was built with WPF. Of course sessions about the new .NET Framework 3.5 and the new Visual Studio Orcas (VS 2008) where not missing. The new VS2008 will include some great new features like multi-target support (.NET 2.0, 3.0 and 3.5), built in ASP.NET AJAX, improved and new designers like a split-screen HTML designer and the new CSS manager, improved javascript debugging and javascript IntelliSense (very handy). And not to forget, LINQ. The major new language feature of the 3.5 framework, making it possible to query various datasources in one unified way. More information about the event including the slides of all the presentations can be found here.
Test Driven Development is a great thing in software development as it makes it possible to verify your code very easily during development and when you have to make changes. However, it is not always easy to write solid unit tests when external influences are involved. For example, in case of Web Services you might want to avoid the actual Web Service calls in your unit tests for reasons like availability, performance, predictability, ... of the Web Service. In my case I had to avoid the Web Services because I couldn't rely on the information they returned (the content of the underlying ERP database was out of my control). To solve this problem for the unit tests and get a predictable response that can be tested there are basically two solutions: - Create a dummy Web Service that replaces the actual Web Service;
- Replace the proxy of Web Service in the project by a dummy proxy.
In my project I choose for the latter on, based on a technique that is described in a blog post by David Waddleton. The trick that makes this technique possible and fairly easy is that the generated proxy is a partial class (.NET 2.0). This makes it possible to define an interface on the generated proxy (without changing it) by writing your own partial class. The service consumer can now communicate with the Web Service using the interface instead of directly to the Web Service. At this point you are free to replace the Web Service implementation for a mock object during the unit tests using some form of dependency injection.
Note: In the picture above the class MyService is displayed as two classes for clarity of the concept, in reality this is only one class implemented in two cs files. Creating the interface might seem to be a lot of work, especially for larger Web Services, but it can easily be generated using the refactor tool [Extract Interface] on the proxy class defined in Reference.cs. The implementation of the partial MyService class stays empty, it only defines the interface IMyService (the implementation of IMyService is in the generated proxy). For dependency injection I've used a simple factory class that either instantiates the Web Service or, in case of the unit tests, an instance of a mock object defined in the web.config. However, as easy this is in C# 2.0 it cannot be implemented the same way in VB.NET. The reason is that VB.NET doesn't support implicit interface implementation, you have to define the interface implementation explicitly using the Implements keyword: Public Function DoSomething() Implements IMyService.DoSomething
End Function
This is too bad because you either have to alter Reference.cs (which you shouldn't because when you update the web reference you loose the changes) or implement new properties/functions in the otherwise empty class MyService and map them to the Web Service, which is a lot more work.
The source code can be downloaded from here: WebServiceMockTechnique.zip (62,52 KB)
In my last post I explained the problems I had running dasBlog in a Partial/Medium Trust environment. There where two problems left, the web.config sections UrlMapper and httpCompress had to be removed and the admin pages return errors.
The first problem can be solved easily by adding the attribute requirePermission="false" to the section declarations (only .NET 2.0), including newtelligence.ControlImages:
<section name="newtelligence.ControlImages"
type="newtelligence.DasBlog.Web.Core.WebControls.ControlImageModuleSectionHandler,
newtelligence.DasBlog.Web.Core"
requirePermission="false"/>
<section name="newtelligence.DasBlog.UrlMapper"
type="newtelligence.DasBlog.Web.Core.UrlMapperModuleSectionHandler,
newtelligence.DasBlog.Web.Core"
requirePermission="false"/>
<sectionGroup name="blowery.web">
<section name="httpCompress"
type="blowery.Web.HttpCompress.SectionHandler, blowery.Web.HttpCompress"
requirePermission="false"/>
</sectionGroup>
The second problem is caused by a line in site.config. In this file there is an entry that references the assembly newtelligence.DasBlog.Web with a public key token of null. However, since all assemblies are now have a Strong Name the public key token has to be filled.
<EntryEditControl>newtelligence.DasBlog.Web.FreeTextBoxAdapter,
newtelligence.DasBlog.Web, Version=1.9.6264.0, Culture=neutral,
PublicKeyToken=123ABC</EntryEditControl>
The public key token can be retrieved from a dll using the sn.exe utility in a command shell:
sn -T newtelligence.DasBlog.Web.dll
At this moment all seems to be working, finally...
... and that was not easy. My first experience with dasBlog was a setup on Windows Vista, this didn't work. The main problem I ran into is described in a blog post of Daddy Starr and might be fixed in the next version of dasBlog, which will be released very soon (DasBlog June 2007 Release). So instead of using one of the latest daily builds I've installed the official community edition (version 1.9.6264.0) on a Windows XP virtual machine and configured it. Now I only had to wait for my host provider creating my new domain, thinking that a copy to my host provider would be all. I was terribly wrong... The environment of my host provider is secured using Partial Trust and Code Access Security, and that is not a good thing when you want to run dasBlog out of the box. The only was solving the problem was downloading the source code and make the following changes: - Remove the usage of XmlNamespaceUpgradeReader to deserialize configuration files like site.config. The implementation is not allowed with Medum Trust and it doesn't seem to be quite necessary (anymore);
- Compile all the assemblies, including all referenced, with a strong name and the attribute AllowPartiallyTrustedCallers.
Now it ran on my XP box with a medium trust but still not at my host provider, I still got security exceptions. To get it finally running I had to remove sections UrlMapper and httpCompress from the web.config. What the consequences will be exactly and why they are not allowed I don't know yet, I will figure it out later. For now the 'outside' of my blog runs, although I do experience some problems with the administrator pages after logging in. BTW. The theme I use is 'business' from a daily build. This theme is designed by Christoph De Baene (delarou), who has done a great job I think.
|