Monthly Archives: May 2007

VSIPFactory – A Software Factory for Visual Studio Extensibility

The VSIPFactory is a software factory for Visual Studio extensibility.

Smart Client Software Factory – May 2007 Release is Live

(From Blaine Wastell's post and Mariano Szklanny's post)

You can now download the SCSF - May 2007 release. The new release provides support for .NET 3.0. The release is propagating to the download servers and should be available when you read this. If not, be patient and try a little later.

The release provides:

  • Windows Presentation Foundation interoperability CAB extensions  and View with presenter recipe (don't miss this post from Miguel Saez for more details)
  • Offline application blocks and recipes; the application blocks support asynchronous calls to WCF web services.
  • Richer ClickOnce Deployment capabilities
  • Enhanced guidance packages which includes code generation Visual Basic .NET 2005 (don't miss this post from Juan Arguello for more details)
  • Improved installation with a new dependency checker
  • Compatibility with Enterprise Library 3.1.

Here are instructions to install the factory. The team has created a new Getting Starting topic on Codeplex. This topic includes instructions to create a Hello World Application with the factory.

Check it out and let them know how you like it.

And this means that the team is going to start it's work on the Web Client Software Factory.

Developer Express won’t be shipping 100 refactorings this year

Mark Miller has broken his promisse of shipping 100 Refactorings in 2007. And I'm glad he did. Read all about it.

Refactor for ASP.NET version 2.2 is out

(This is not new, but ...)

Refactor! for ASP.NET version 2.2 is shipping. Built by Developer Express, this FREE code refactoring tool includes 29 time-saving refactorings and is available to all developers working in Visual Studio 2005 and Orcas Beta 1.

Read all about it in Mark's blog.

UPDATE: Extension methods

Looks like I was way wrong in here and here.

I had thought that from the top of my head because I tried to use Array.IndexOf as an extension method and was surprised to see that it wasn't an extension method.

It presented a good opportunity to play around with extension methods, so I wrote a class to extend the Array class:

public static class ArrayUtils

{

    public static int IndexOf<T>(this T[] array, T value)

    {

        return System.Array.IndexOf(array, value);

    }

 

    public static int IndexOf<T>(this T[] array, T value, int startIndex)

    {

        return System.Array.IndexOf(array, value, startIndex);

    }

 

    public static int IndexOf<T>(this T[] array, T value, int startIndex, int count)

    {

        return System.Array.IndexOf(array, value, startIndex, count);

    }

}

It was so easy that I thought: "Why dind't they do it?".

While I was trying to write a proof of concept around making such a change in a class (changing normal static methods into extension methods). It was as simple as adding a this keyword:

public class MyClass

{

    private int myField;

 

    public int MyProperty

    {

        get { return myField; }

        set { myField = value; }

    }

 

    public static bool IsNullOrEmpty(this MyClass value)

    {

        if (value == null) return true;

        if (value.myField == 0) return true;

        return false;

    }

}

The output of the compiler just chilled my enthusiasm:

MyCsClass.cs(18,47): error CS1106: Extension methods must be defined in a non generic static class

What is this all about? How had I missed it in here and here?

Here's how I had missed it:

http://search.msdn.microsoft.com/search/Default.aspx?brand=msdn&query=%22non-nested%22+%22non-generic%22+%22static+class%22+%22extension+methods%22

http://search.live.com/results.aspx?q=%22non-nested%22+%22non-generic%22+%22static+class%22+%22extension+methods%22

I should have tried this:

http://www.google.com/custom?client=pub-3578125481836759&channel=1972798655&cof=S%3Ahttp%3A%2F%2Fsearchdotnet.com%2Fdefault.aspx%3BCX%3ADotNet%2520Developers%2520Search%2520Engine%3BL%3Ahttp%3A%2F%2Fwww.searchdotnet.com%2Fimages%2Fsearchnet.jpg%3BLH%3A36%3BLP%3A1%3B&q=%22non-nested%22+%22non-generic%22+%22static+class%22+%22extension+methods%22

THIS is the most recent (I think) specification of C# 3.0 and it states that:

Extension methods are declared by specifying the keyword this as a modifier on the first parameter of the methods. Extension methods can only be declared in non-generic, non-nested static classes.

Now it's all clear!

How about a keyword for qualifying static members?

I like to always qualify all instance fields with the this keyword.

this.someInstanceField;

this.GetType();

I would like to do the same for static fields, but there's no keyword for that.

I've been thinking about this for a while and I think I found a solution: the static keyword.

typeof(); // no need for the static keyword

static.someStaticField;

Extension methods missing from System.Array in the .NET Framework 3.5 (Beta 1)

UPDATE: Extension methods

Extension methods are a feature of the new C# language specification (also available in Visual Basic [^] [^]):

This new feature should be used in existing classes like the Array class by making the folowing methods extension methods:

public static System.Collections.ObjectModel.ReadOnlyCollection<T> AsReadOnly<T>(this T[] array);

public static int BinarySearch<T>(this T[] array, T value);

public static int BinarySearch(this Array array, object value);

public static int BinarySearch<T>(this T[] array, T value, System.IComparer<T> comparer);

public static int BinarySearch<T>(this T[] array, int index, int length, T value);

public static int BinarySearch<T>(this T[] array, int index, int length, T value, System.IComparer<T> comparer);

public static void ConstrainedCopy<T>(this T[] sourceArray, int sourceIndex, T[] destinationArray, int destinationIndex, int length);

public static TOutput[] ConvertAll<TInput, TOutput>(this TInput[] array, System.Converter<TInput, TOutput> converter);

public static void Copy<T>(this T[] sourceArray, T[] destinationArray, int length);

public static void Copy<T>(this T[] sourceArray, T[] destinationArray, long length);

public static void Copy<T>(this T[] sourceArray, int sourceIndex, T[] destinationArray, int destinationIndex, int length);

public static void Copy<T>(this T[] sourceArray, long sourceIndex, T[] destinationArray, long destinationIndex, long length);

public static bool Exists<T>(this T[] array, System.Predicate<T> match);

public static T Find<T>(this T[] array, System.Predicate<T> match);

public static T[] FindAll<T>(this T[] array, System.Predicate<T> match);

public static int FindIndex<T>(this T[] array, System.Predicate<T> match);

public static int FindIndex<T>(this T[] array, int startIndex, System.Predicate<T> match);

public static int FindIndex<T>(this T[] array, int startIndex, int count, System.Predicate<T> match);

public static T FindLast<T>(this T[] array, System.Predicate<T> match);

public static int FindLastIndex<T>(this T[] array, System.Predicate<T> match);

public static int FindLastIndex<T>(this T[] array, int startIndex, System.Predicate<T> match);

public static int FindLastIndex<T>(this T[] array, int startIndex, int count, System.Predicate<T> match);

public static void ForEach<T>(this T[] array, Action<T> action);

public static int IndexOf<T>(this T[] array, T value);

public static int IndexOf<T>(this T[] array, T value, int startIndex);

public static int IndexOf<T>(this T[] array, T value, int startIndex, int count);

public static int LastIndexOf<T>(this T[] array, T value);

public static int LastIndexOf<T>(this T[] array, T value, int startIndex);

public static int LastIndexOf<T>(this T[] array, T value, int startIndex, int count);

public static void Resize<T>(this ref T[] array, int newSize);

public static void Sort<T>(this T[] array);

public static void Sort<T>(this T[] array, System.IComparer<T> comparer);

public static void Sort<T>(this T[] array, System.Comparison<T> comparison);

public static void Sort<TKey, TValue>(this TKey[] keys, TValue[] items);

public static void Sort<T>(this T[] array, int index, int length);

public static void Sort<TKey, TValue>(this TKey[] keys, TValue[] items, System.IComparer<TKey> comparer);

public static void Sort<T>(this T[] array, int index, int length, System.IComparer<T> comparer);

public static void Sort<TKey, TValue>(this TKey[] keys, TValue[] items, int index, int length);

public static void Sort<TKey, TValue>(this TKey[] keys, TValue[] items, int index, int length, System.IComparer<TKey> comparer);

public static bool TrueForAll<T>(this T[] array, System.Predicate<T> match);

This would allow us to write code like this:

if (someArray.IndefOf(someValue))

{

    //...

}

If you would like to see this in the next release of the .NET framework, vote on this suggestion.

Extension methods missing from System.String in the .NET Framework 3.5 (Beta 1)

UPDATE: Extension methods

Extension methods are a feature of the new C# language specification (also available in Visual Basic [^] [^]):

This new feature should be used in existing classes like the String class by making the folowing methods extension methods:

public static int Compare(this string strA, string strB);

public static int Compare(this string strA, string strB, bool ignoreCase);

public static int Compare(this string strA, string strB, System.StringComparison comparisonType);

public static int Compare(this string strA, string strB, bool ignoreCase, System.Globalization.CultureInfo culture);

public static int Compare(this string strA, int indexA, string strB, int indexB, int length);

public static int Compare(this string strA, int indexA, string strB, int indexB, int length, bool ignoreCase);

public static int Compare(this string strA, int indexA, string strB, int indexB, int length, System.StringComparison comparisonType);

public static int Compare(this string strA, int indexA, string strB, int indexB, int length, bool ignoreCase, System.Globalization.CultureInfo culture);

public static int CompareOrdinal(this string strA, string strB);

public static int CompareOrdinal(this string strA, int indexA, string strB, int indexB, int length);

public static string Concat(this string str0, string str1);

public static string Concat(this string str0, string str1, string str2);

public static string Concat(this string str0, string str1, string str2, string str3);

public static string Copy(this string str);

public static string Intern(this string str);

public static string IsInterned(this string str);

public static bool IsNullOrEmpty(this string value);

This would allow us to write code like this:

if (someString.IsNullOrEmpty())

{

    //...

}

If you would like to see this in the next release of the .NET framework, vote on this suggestion.

The search engine every .NET developer was looking for

While watching this DotNetRocks show, I came across the SearchDotNet engine.

SearchDotNet comes in three flavors:

SearchDotNet has OpenSearch support which means that it can be added to the list of search engines in IE7 or Firefox 2.0 (or other OpenSearch client).

Daniel Appleman also keeps a list of other similar custom search engines.

Optimizing reading for the CustomTextMessageEncoder

Continuing the improvement of the CustomTextMessageEncoder (see this and this), this time I'll use the XmlDictionaryWriter instead of the XmlTextWriter whenever the character encoding is utf-8, utf-16 or Unicode.

To achieve this, all that's needed is to look into the character set part of the content type and act accordingly.

public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)

{

    byte[] messageContents = new byte[buffer.Count];

    Array.Copy(buffer.Array, buffer.Offset, messageContents, 0, messageContents.Length);

    bufferManager.ReturnBuffer(buffer.Array);

 

    MemoryStream stream = new MemoryStream(messageContents);

    //return ReadMessage(stream, int.MaxValue);

    return ReadMessage(stream, int.MaxValue, contentType);

}

 

public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType)

{

    string charset = null;

    if (!string.IsNullOrEmpty(contentType))

    {

        System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(contentType);

        charset = ct.CharSet;

    }

    if ((!string.IsNullOrEmpty(charset)) && (charset.Equals(ValidatingUTF8.WebName, StringComparison.InvariantCultureIgnoreCase) || charset.Equals(ValidatingUTF16.WebName, StringComparison.InvariantCultureIgnoreCase) || charset.Equals(ValidatingBEUTF16.WebName, StringComparison.InvariantCultureIgnoreCase)))

    {

        XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, XmlDictionaryReaderQuotas.Max);

        return Message.CreateMessage(reader, maxSizeOfHeaders, this.MessageVersion);

    }

    else

    {

        XmlReader reader = XmlReader.Create(stream);

        return Message.CreateMessage(reader, maxSizeOfHeaders, this.MessageVersion);

    }

}