September 2003 - Posts

Tom talks about the MSDN Chat about "Visual Basic .NET Language Design". Thx for sharing the info Tom, because I couldn't attend the chat!

Skype
What is Skype? “Skype is the next phenomenon from the people who brought you KaZaA. Just like KaZaA, Skype uses P2P (peer-to-peer) technology to connect you to other users – not to share files this time, but to talk for free with your friends.” Ok, big deal you could say, we already have Messenger. But I recently had some problems making voice connections to family with Messenger. Even when they were using one of the most recent ADSL Routers, with UPnP enabled, I couldn't connect. So I gave Skype a try and I must say I was amazed; not only the sound quality is in my opinion even better than Messenger, but Skype could make connections to pc's behind firewalls and/or routers. Installation and account creation is very easy, connections are made within a second. Ofcourse they have not (yet?) the huge user base like Messenger, and their focus is on voice communications, but I keep this little program so I can voice chat with people to Messenger can not connect.

Click the link on my blog, to call me!

C# HandleWhiteSpace Add-In
From the authors website: The C# code editor in Visual Studio.NET does not handle whitespaces automatically like the VB.NET code editor does. This Add-In solves this problem by adding the 'Handle WhiteSpace' menu option to the Visual Studio.NET Tools menu. This option formats the C# code of the active code editor. This includes:

  • Space before:  method declaration parentheses, method call parentheses, statement parentheses, braces and brackets
  • Space after: comma and semicolon
  • Space around: operators
  • Double space

The author, Fons Sonnemans, sent me an email pointing me to this little utility he hase created. Check out the other downloads, some cool stuff!

Component developers have to make decisions all the time about how to flexible their components need to be. They need to find the balance between flexibility and development duration: if they want to increase the flexibility, they probably need to spend more development time. How to implement the needed flexibility depends on the situation. In some cases it is needed that the components must execute code that will be written by developers that actually use these components, so that code is not yet available while designing the component. In other cases it may be required something changes depending on a setting, for example how Customers are displayed (first name + last name, last name + initial, …). Providing this kind of flexibility in your components can require a rather complex model to be able to determine what the ToString method of the Customer object needs to return. But this kind of flexibility could quite easy be accomplished if you only could put some code in a String, and let this code be evaluated by your component. Of course you’d want to avoid writing your own parser for such a String at all times, so what could be of any help? CodeDom and Reflection can be used for solving this kind of problems.

CodeDom can be used mainly for two goals: compilation at runtime and code generation. It is possible to define a class in memory using the CodeDom, and let it compile at runtime, so you can use the class you’ve constructed in your code, as a compiled class! But once you’ve defined that class using CodeDom, you can easily generated VB.NET or C# code for it. Reflection can be used to investigate and invoke objects at runtime. For example you can use Reflection to iterate through all properties or methods of a class, and invoke them when needed. In my opinion the CodeDom – Reflection combination is one on the great concepts in .NET. Let’s find out how to use them for the “flexibility problem”!

For example, you want to build a component that has a Customer class which’ ToString function can be determined when instantiating Customer instances. Let’s say the Customer class has two properties Name and Street. The flexible part of our Customer class is that we can determine how the ToString method will be implemented. For example:
Customer c = new Customer("customer.Name");
c.Name = "Jan";

If the ToString method of this customer object would be called, the string “Jan” would be returned. When we would instantiate the customer class as shown below, the result of the ToString method would be “JAN”, because of the ToUpper() function call:
Customer c = new Customer("customer.Name.ToUpper()");
c.Name = "Jan";

Notice that the same Customer class is used to obtain that result, and even complex functions can be used:
Customer c =
 new Customer("customer.Name + \" (\" + customer.Name.Length + \")\"");
c.Name = "Jan";

The result of invoking the ToString method would be “Jan (3)”. Notice that the quotes are escaped because you’ll have to put them in a String. Without the escaping that string looks like: customer.Name + “ (“ + customer.Name.Length + “)”

To obtain this behaviour the implementation of the ToString function on the Customer class is:
public override string ToString()
{
 Assembly ass;

 if(!AssemblyCache.ContainsKey(this.GetType().Name + _toString))
 {
  //Create the class definition using CodeDom
  CodeTypeDeclaration tempClass = new CodeTypeDeclaration("TempClass");
  tempClass.IsClass = true;
  CodeMemberMethod tempMethod = new CodeMemberMethod();
  tempMethod.Name = "GetValue";
  tempMethod.Attributes = MemberAttributes.Public;
  tempMethod.ReturnType = new CodeTypeReference(typeof(string));
  tempMethod.Parameters.Add(
   new CodeParameterDeclarationExpression(this.GetType(), "customer"));
  tempMethod.Statements.Add(
   new CodeMethodReturnStatement(
   new CodeSnippetExpression(this._toString)));
  tempClass.Members.Add(tempMethod);
 
  //Compile that class
  CodeCompileUnit unit = new CodeCompileUnit();
  CodeNamespace ns = new CodeNamespace("Temp");
  ns.Types.Add(tempClass);
  unit.Namespaces.Add(ns);
  CompilerParameters compilerParams = new CompilerParameters();
  compilerParams.GenerateInMemory = true;
  string assemblyFileName =
   Assembly.GetExecutingAssembly().GetName().CodeBase;
  compilerParams.ReferencedAssemblies.Add(
   assemblyFileName.Substring("
file:///".Length));
  ICodeCompiler compiler =
   new Microsoft.CSharp.CSharpCodeProvider().CreateCompiler();
  CompilerResults results =
   compiler.CompileAssemblyFromDom(compilerParams, unit);
  ass = results.CompiledAssembly;
  
  //Add compiled assembly to cache
  AssemblyCache.Add(ass, this.GetType().Name + _toString);
 }
 else
 {
  ass = AssemblyCache.GetAssembly(this.GetType().Name + _toString);
 }

 //Create an instance of the compiled class
 Type tempClassType = ass.GetType("Temp.TempClass");
 object tempClassInstance = Activator.CreateInstance(tempClassType);

 //Call the GetValue method of the TempClass instance
 //using Reflection.
 MethodInfo getValueMethod = tempClassType.GetMethod("GetValue");
 
 return (string)getValueMethod.Invoke(
  tempClassInstance,new object[] {this});
}

First the AssemblyCache is checked to find out if the required code is already compiled before. This cache is implemented using the Singleton design pattern, for the complete code, look at the end of this post. If the code was not yet compiled before, a new CodeTypeDeclaration instance is created that will represent a new class that will be compiled in memory. A new CodeMemberMethod is added to that class, representing the GetValue function. This function contains only one line: the return statement. This return statement executes the code that is passed in the constructor and stored in the _toString variable. At that point the class is finished, so a CodeCompileUnit is created, containing a Namespace that contains the temporary class. To compile that unit, a Compiler object is obtained from the CsharpCodeProvider. The resulting assembly is placed in the cache.

So now, we have a compiled assembly containing the code that we passed in the constructor. To actually use the temporary class, Reflection comes into play. First we need to retrieve a Type instance from that Assembly. Then a MethodInfo object is created, that represents the GetValue method. This MethodInfo object is used to invoke the method, and the result is used as return value. It’s that simple!

The AssemblyCache class is implemented like this:
public class AssemblyCache
{
 static System.Collections.Hashtable assemblies =
  new System.Collections.Hashtable();

 public static bool ContainsKey(string key)
 {
  return assemblies.ContainsKey(key);
 }

 public static void Add(Assembly ass, string key)
 {
  assemblies.Add(key, ass);
 }

 public static Assembly GetAssembly(string key)
 {
  return (Assembly)assemblies[key];
 }

 private AssemblyCache()
 {
  //Singleton!
 }
}

As you can see, CodeDom and Reflection can give developers a great ability to create very flexible components. If you need the complete source code of the example, contact me so I can send you the solution, or I’ll publish it so you could download it.

Tom and Gerd have updated the MSDN Belux site. They do this every week, but this time they have introduced some nice features (see Tom's post). There is a page about how you can participate in the Belux MSDN Community, so every developer in the Belux (Belgium and Luxembourg) should take a look. A list of bloggers in the Belux is added too.

But, a little bit hidden in my opnion, a link to the brand new MS Belux Forums is included too! This forum could use some more publicity, but I'm confidend something like that is planned. Nice work!

My new article for MSDN Belux is online!

<quote>
Summary: Sometimes things can go wrong when code is executed, so Exceptions are thrown. When your application exposes services through a webservice layer, SoapExceptions are thrown from the server to the client. By default normal Exceptions are converted to a SoapException, resulting in a rather ugly Exception containing all information concatenated in a long String. But luckily the SOAP protocol allows any XML document to be included in SOAP error messages. This article shows how to build some helper classes to easily pass error information from the server to the client through a webservice layer.
</quote>

I would like to say thanks to Tom for doing the layout and publishing the article.

David McNamee has a post about what the next version of VB.NET will offer:

  • Disposable code: no need to create a new project just to try something out. (Some serious competition for Snippet Compiler, which is also great) This one is a nice-to-have feature, but not a big breakthrough...
  • Code editor improvements: collapsable attributes.
  • XML documentation. Finally! Too bad for VB-DOC and others, but they were great utils...
  • Forms editor improvements: alignment of controls.
  • Generics
  • New keyword: “My” that gives access to common resources (e.g. printer).
  • Debugging improvements: immediate invocation (without building or running) in the Immediate window and (last but not least) edit&continue.

Edit&continue is a great feature. I have to agree it can be abused and can lead to “just give it a try, let's see if it works“ scenarios. But if you use it wisely it can greatly improve productivity at least a few times a day. A video of the next VB.NET version is available here.

 

Article on The Register about Mono:

<quote>
Mono, the open source implementation of Microsoft's .NET Web services platform, can dramatically improve developer productivity, according to the leading light of the project.

Miguel de Icaza, CTO and co-founder of open source firm Ximian, which was acquired by Novell last month, took centre stage at the company's BrainShare onference in Barcelona today.

de Icaza told delegates a "large and growing developer community", including 150 external contributors, is working on Mono, which remains on track for a 1.0 release by the end of the year.

Mono enables Unix and Linux interoperability for emerging .NET applications and environments while allowing developers to write in more higher level, richer programming languages.

According to de Icaza, Mono is stable: four ISVs have already developed applications based on Mono - a sign of the growing maturity of the platform, he says.
</quote>

Paul Vick (technical lead of VB.NET)  has posted a nice entry about the edit and continue feature that will be available in the next version of VB.NET. He discusses the danger of introducing this advanced feature, for developers that are not so experienced. In my opinion, edit and continue is abused sometimes be less experienced developers and maybe even by experienced developers. But I think it can be very useful too, if you use it wisely! Paul uses the methaphore of cars to explain why he thinks this feature should be included.

But Paul introduces a new (and fun) feature to prevent unexperienced developers to use the advanced features. I guess the feature will not be in VS.NET 2004...
<quote>
We sometimes joke that we should build a feature into the program that turns off all the "advanced" features of the product. Then, when you try to use one of them, we would pop up a dialog that says "You're trying to use an advanced feature. Before we can let you use this, you must answer the following questions correctly:" and then test them to see if they're advanced enough to really use the feature. It's tempting but, of course, it would never work. Just as no one thinks they are a below-average driver, most people wouldn't appreciate being told that they aren't "advanced" enough of a programmer to use a feature...
</quote>

Christian Nagel has published a list of INETA speakers, it seems Michiel van Ottegem will come to Belgium and speak about ASP.NET V2. Cool!

Last friday I attended an event of the Belgian .NET User Group (Benug) about service-oriented architectures in .NET. The presenter was Peter Himschoot (replacing his colleague Patrick Tisseghem) who did a very good job. The session was spit into a theoretical part and a hands-on workshop.

On tip Peter showed us, I would like to share: “Set StartUp Projects ...”. I guess everybody knows how to set a StartUp Project in a Visual Studio.NET solution; just right click on the project item in the Solution Explorer and choose “Set as StartUp Project”. But you can start and debug multiple projects at the same time! If you right click on the Solution Item instead of the Project Item, and then click “Set StartUp Projects...” you can choose between “Singe StartUp Project” and “Multiple StartUp Projects”. For the second choice you can select the Projects of your Solution you want to start when you hit the F5 or Start button. This is very useful for debugging multi-tier projects. Thanks Peter!

More Posts