October 2006 - Posts
The latest update (1.8) of my article Commonly Used .NET Coding Patterns in CodeDom is now out.
Changes made since 1.7:
- The Code Access Security Decorator Patterns have been added.
- The Assembly Information Pattern has been added.
- Security demand added to GetObjectData in the Serializable Type Pattern.
- Xml Comment Patterns moved to .Xml namespace and had their CodeXmlComment prefix removed (too long).
- Binaries now target .NET 2.0 instead of .NET 1.1, but they are still mostly backwards compatible.
The project is now hosted on CodePlex, complete with forums, an rss feed, an issue tracker and the whole nine yards. As always, suggestions are more than welcome.
Duck Typing is a very nice mechanism and Guenter Prossliner's article does it justice by introducing it to .NET with NDuck.
Duck Typing is a way to create a strongly typed wrapper at runtime that would take a type and 'force it' to implement an interface, instead of looking for the contract dynamically:
Before:
public static void SetImage(object owner, string resourceName){
PropertyInfo piImage = owner.GetType().GetProperty("Image");
EventInfo eiDisposed = owner.GetType().GetEvent("Disposed");
if (piImage == null || piDisposed == null)
throw new ArgumentException("The 'owner' object" +
" is not compatible with the required interface!");
Stream imgStream =
typeof(ImageTools).Assembly.GetManifestResourceStream(resourceName);
Image image = Image.FromStream(imgStream);
piImage.SetValue(owner, image, new object[0]);
EventHandler disposedHandler = delegate(object sender, EventArgs e){
image.Dispose();
imgStream.Dispose();
};
eiDisposed.AddEventHandler(owner, disposedHandler);
}
// Calling code
ImageTools.SetImage(this.PictureBox1, "Image");
ImageTools.SetImage(this.Label1, "Image2");
After:
public interface IImageContainer{
Image Image{set;}
event EventHander Disposed;
}
public static class ImageTools {
public static void SetImage(IImageContainer obj, string resourceName){
Stream imgStream =
typeof(ImageTools).Assembly.GetManifestResourceStream(resourceName);
Image image = Image.FromStream(imgStream);
obj.Image = image;
// ensure that the Image and the Stream will
// be closed when the PictureBox is diposed.
obj.Disposed += delegate(object sender, EventArgs e){
image.Dispose();
imgStream.Dispose();
};
}
}
// Calling code
ImageTools.SetImage(
DuckTyping.Implement<IImageContainer>(this.PictureBox1), "Image");
ImageTools.SetImage(
DuckTyping.Implement<IImageContainer>(this.Label1), "Image2");
I haven't talked about my new weblog over at Microsoft Israel's Blogs yet, but there couldn't be a better time, since I've just written a post about the Third Israeli Blogger Dinner there! Hurrah! :)
If you're looking for the technical content I write here (everything is cross-posted to that weblog) plus some extra content in Hebrew, you should consider subscribing to that weblog (rss/atom) instead. On the other hand, you could simply subscribe to the original content category on it for only the Hebrew posts and keep the asp.net feed as is.
The third, and IMHO best option of the three, is to subscribe to the main feed, since there are a lot of very good bloggers there.
Because CodeDom is so verbose and uses a massive grid of objects to represent code structures, it also has many small reusable objects, such as CodeTypeReference objects. Many people overlook this fact because there are so many object being created anyway, but sometimes a certain object will be used over and over. Since both the creation of these objects takes time and they also take up memory as unnecessary copies, consider creating a cache.
For example, for the next release of the CodeDom Patterns library, I've created a cache for CodeTypeReference objects:
using System;
using System.Collections.Generic;
using System.CodeDom;
namespace DotNetZen.CodeDom
{
/// <summary>
/// Acts as a cache for <see cref="CodeTypeReference"/> objects.
/// </summary>
public static class CodeTypeReferenceStore
{
private static Dictionary<RuntimeTypeHandle, CodeTypeReference> typeReferences =
new Dictionary<RuntimeTypeHandle, CodeTypeReference>();
private static Dictionary<string, CodeTypeReference> nameReferences =
new Dictionary<string, CodeTypeReference>();
/// <summary>
/// Gets a <see cref="CodeTypeReference"/> by the <see cref="Type"/> it should reference.
/// </summary>
/// <param name="type">The type being referenced.</param>
/// <returns>A <see cref="CodeTypeReference"/> object.</returns>
public static CodeTypeReference Get(Type type)
{
RuntimeTypeHandle handle = type.TypeHandle;
if (!typeReferences.ContainsKey(handle))
{
typeReferences.Add(handle, new CodeTypeReference(type));
}
return typeReferences[handle];
}
/// <summary>
/// Gets a <see cref="CodeTypeReference"/> by the name of the <see cref="Type"/> it should reference.
/// </summary>
/// <param name="type">The name of the type being referenced.</param>
/// <returns>A <see cref="CodeTypeReference"/> object.</returns>
public static CodeTypeReference Get(string typeName)
{
if (!nameReferences.ContainsKey(typeName))
{
nameReferences.Add(typeName, new CodeTypeReference(typeName));
}
return nameReferences[typeName];
}
}
}
Now that I have the time for it, I'm going through a lot of material I've been collecting in my To Read folder over the past year or so. One of the videos I watched is Mike Barnett's talk about Spec# at the recent Lang.NET Symposium.
What Spec# does, in a few words, is to add contracts to your code: Your method never returns null? Set this as a contract and everyone calling your method could rely on this; Should you always receive a number between x and y into a certain parameter? Set this as a contract and no one can call your method before their code explictly shows that the parameter is between those boundries.
Except for the fact that it shows some awesome concepts in keeping everything nice, clean and also reduces the amount of unit testing required by using these contracts, it made me say "woah, I didn't even think of that," when the squiggly lines started appearing in places I hadn't expected (yes, it works in the background and shows you problems as you code). However, I can't seem to stop thinking that Spec# has one huge fault: Out of all of the developers I have ever worked with, about 90% will never use it unless they are forced too, which is sad. I feel this is going the way of checked exceptions in Java, where the functionality is there and is great when used, but most people just don't use it because it's less work and the code still works.
I, for one, would love to see Spec# embedded into C# 4.0 (my guess is it won't be ready for 3.0), after the syntax is cleaned up a bit. I think it's a great and welcome step forward in code-hardening, but its biggest problem is how to make Spec# such an integral part of C# so that it doesn't follow the footsteps of other great software features no one ever uses.
Remember the game Connect the Dots we used to play as kids? It was fun and easy and you could color the pretty bunny after you were done.
This gave me an idea - a computer program doesn't know how to play Connect the Dots very well unless it's programmed to do just that. A computer program meant to crack normal CAPTCHAs would simply start listing the numbers appearing near the dots as the solution and be done with it.
To the left of this text you can see the output of a little program I created in a couple of hours. Given the dot coordinates for letters (on a 4x5 grid), it creates bitmaps of words from said letters. For you and me, it might take a few seconds to realize what connecting the dots gets you, but for a computer program it's extremely hard. Add a few extra difficulties like most of today's current CAPTCHAs have (geometric shape underlays/overlays, distortion, noise, font changes, etc.) and the fact that no CAPTCHA breaking program would expect it and you might get an (almost) unbeatable CAPTCHA.
If I only could, I'd embed it in my own weblog because comment spam here is horrible.
My new Linq Extensions project for the Linq May CTP is now up on CodePlex and I've released beta 1 (numbered 0.1).
It took me a while to understand how to work with it and the connection to the Team Foundation Server wasn't as fast as I had hoped, but now it's ready for use.
Currently implemented are the following:
- Hierarchy
- Reverse Hierarchy
- Binary Tree
- Infix Traversal
- Prefix Traversal
- Postfix Traversal
- Graphs
- Breadth-First Traversal
- Depth-First Traversal
- In
A FAQ and examples will be written soon, but it's pretty straight forward. You can open bugs and feature requests using the Issue Tracker. The release is downloadable here.
PS: Since the System.Query assembly is not signed, which I'm guessing is because this is only a CTP, so the DotNetZen.Query assembly is not signed.
While watching the MSDN Nugget on Application Settings in Visual Studio 2005, I found a couple of things I found weird about the default application settings provider, LocalFileSettingsProvider:
- When saving to Application Data\<Application>\<Assembly>\<Version>, the provider ignores the fact that there is already a mechanism called Isolated Storage already built-into the .NET Framework and instead implements it by itself. This feels like the NIH (Not Invented Here) antipattern.
Isolation is by either the tuple (Assembly, User, Version) or the tuple (Assembly, Version), so settings do not survive versioning. Fabrice explains in a comment that this is what the Upgrade method is for. Cool.
These might be true for other providers, but I haven't checked them out yet. Anyone from Microsoft care to shed some light on these?
Ever since Kathy Kam announced on her weblog that a new type named TimeZone2 will be introduced into the Orcas release of .NET, the community has been in an uproar, claiming the new name is horrible and that we're going back to the days of Win32 and COM with types like TimeZone3 and DateTimeEx not far down the line.
TimeZone2 comes to replace TimeZone in order to support Vista's Dynamic Time Zone APIs and offer some other new functionality.
According to Krzysztof, the team had several options:
- Deprecate the current TimeZone using ObsoleteAttribute and use the same type for the new functionality, but this, according to Krzysztof, will simply not happen.
- Use a new namespace, but this will cause confusion, since the type name would have to be fully qualified.
- Find a better name, yet no one has been able to come up with one that would satisfy the team.
- Call it TimeZone2.
Unfortunately, they decided on the last option, backed by an invocation of a Design Guideline (And none other than one of the very few guidelines I wholeheartedly disagree with).
I, personally, am with the Break Camp: Simply take the old functionality and deprecate it or just remove it altogether. The Orcas framework is to be released at version 3.* (a change of the major version since the last release), which means to users that breaking changes are acceptable and even expected. I have never heard known of a single serious software developer that has taken for granted that their applications will simply work when moving from .NET 1.0 to .NET 2.0 and I don't think I'll ever hear of one blindly moving to .NET 3.0.
Want to make it easier on your customers? Create an automatic tool (maybe as part of Visual Studio Orcas) that translates current behaviour to 3.0 behaviour.
Invoking the Red-Bits-In-Place-Service-Pack excuse is moot here, since it was the wrong call to make in the first place. Backwards compatability is not the Holy Grail.
This is the very first step on the road to making the .NET Framework an unusable patch-work. Just imagine a developer new to .NET which starts with version 3.0 and sees TimeZone and TimeZone2.
The CLR Team's posts about this in chronological order:
Orcas September CTP available... Hello "System.TimeZone2"!
System.TimeZone2 Starter Guide [Kathy Kam]
Designing System.TimeZone2 - Part 1 (API naming and new class or not)
Designing System.TimeZone2 - Part 2 (Dynamic Time Zone support)
System.TimeZone2 Naming ... and related design guidelines
Naming Guideline Discussion
When there is no good name...
[Update: The team went back to the whiteboard and renamed it TimeZoneInfo.]
Andrew Stopford has an interesting couple of posts on the CLR's support for generic type variance[1] in version 2.0, and the lack of which in C# 2.0. I join Andrew in wishing this would be implemented in C# 3.0 (or at least in an interim '2.1' release with .NET 3.0).
Be sure to read the comments on those posts too for some more in-depth information about this.
[1] Generic type variance means that List<string> is a List<object>, just like string[] is a object[].
More Posts
Next page »