Why I wasn't reading his blog before, I can't explain
I've learned something from everything I've ever read by him, so why did it take this long to subscribe to his blog? Don't repeat my error, read Guy Kawasaki. Please?
All the (developer) news that's unfit to read...
I've learned something from everything I've ever read by him, so why did it take this long to subscribe to his blog? Don't repeat my error, read Guy Kawasaki. Please?
Posted by IDisposable at 1/26/2006 02:24:00 AM 0 comments
The best value in source code has been updated once again. Today Paul Wilson released 4.2.1.0 of his most-excellent Wilson ORMapper. At $50 USD, you will not find a better deal in all of the .Net kingdom. It's good code, and the functionality is just right without the serious overkill that plagues other alternatives. Sure, it's not nHibernate, and nHibernate is free; but honestly the complexity of nHibernate is much more of a cost versus the simplicity and obviousness of WORM (and the attendant cost savings). I know it has saved me an hour or two... what is that in today's consulting rates? In other news, the vaporware specification from Microsoft (ObjectSpaces) has still not shipped... Wilson ORMapper Latest News v4.2.0.1 Released
Posted by IDisposable at 1/24/2006 11:50:00 PM 2 comments
The St. Louis Code Camp is Coming! Looks like we finally exist! I'm not sure what anyone might learn from me, perhaps decent SQL optimizing or the evils of premature optimization? Do any of my readers have requests?
Posted by IDisposable at 1/22/2006 06:12:00 PM 0 comments
Good news: Microsoft recently released some localized versions of the .Net Framework 2.0. These language packs are downloadable from the link below. Bad news: Microsoft still doesn't really get it when offering downloads in alternate languages. What do I mean? Click this link .NET Framework Version 2.0 Language Pack. It'll be in English (nice, as that's the specified display language in the URL). Now click the Download button. You'll get a lovely popup (that may or may not be sized to a readable size). That popup says that there IS NO English language pack. Funnny, huh? That they didn't bother to explain that the English localization is built into the primary release of the .Net Framework is not my complaint. That they wasted my time in even offering an English version is also not my complaint. Here's my complaint, return to the first page, select any other language and click the Change button. Now you get a version that offers another download, and that one will be localized to the selected language. But so will the download screen! That's just dumb. Even worse is that the file you download is always going to be called langpack.exe (not a different filename for each locale). Even worse is that now the Change Language dropdown now has the language names in the language you picked to download. The concept of what file to download (which language pack) is very different than the UI language of the page (which should driven by the browser accept for culture).
Posted by IDisposable at 1/19/2006 04:29:00 PM 0 comments
I've had this class around for a long time, finally decided to update it to use generic types instead of tons of overloads. It's tons nicer this way. Contact me if you want a version with XML documentation (which just looks ugly in the blog).
using System; using System.ComponentModel; using System.Diagnostics; namespace IDisposable.Utilities { public static class ArgumentValidation { #region Helper private static string PadWord(string text) { if (String.IsNullOrEmpty(text)) return string.Empty; else return text + " "; } #endregion public static void ArgumentDifferentTypeCheck(object value, string name, Type type) { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentNullCheck(type, "type"); if (value.GetType() != type) { throw new ArgumentException( string.Format("Argument {0}must be of type {1}.", ArgumentValidation.PadWord(name), type.Name), name); } } public static void ArgumentIncompatibleTypeCheck(object value, string name, Type type) { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentNullCheck(type, "type"); if (!type.IsAssignableFrom(value.GetType())) { throw new ArgumentException( string.Format("Argument {0}must be compatible with type {1}.", ArgumentValidation.PadWord(name), type.Name), name); } } public static void ArgumentNullCheck(object value, string name) { if (null == value) { throw new ArgumentNullException(name, string.Format("Argument {0}cannot be null.", ArgumentValidation.PadWord(name))); } } public static void ArrayArgumentDifferentRank(Array value, string name, int rank) { ArgumentValidation.ArgumentNullCheck(value, "value"); if (value.Rank != rank) { throw new RankException(string.Format("Argument {0}must be " + "an array with {1} dimension.", ArgumentValidation.PadWord(name), rank)); } } public static void ArgumentInvalidEnumValueCheck(object value, string name, Type enumType) { Debug.Assert(value.GetType().IsPrimitive || (value.GetType() == typeof(string)) , "Expected a primitive type or a String!"); ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentNullCheck(enumType, "enumType"); if (enumType.GetCustomAttributes(typeof(FlagsAttribute), true).Length > 0) { throw new ArgumentException(string.Format( "Cannot validate against the type {0} because it has the custom attribute FlagsAttribute." , enumType), "enumType"); } if (!Enum.IsDefined(enumType, value)) { if (value.GetType() == typeof(string)) { // Let the value argument be int.MaxValue if a string was passed in. throw new InvalidEnumArgumentException(name, int.MaxValue, enumType); } else { int valueInt32 = 0; TypeConverter typeConverter = TypeDescriptor.GetConverter( Enum.GetUnderlyingType(enumType)); try { valueInt32 = (int)typeConverter.ConvertTo(value, typeof(int)); } catch (OverflowException) { // Let the value argument be 0 if it overflows Int32. } throw new InvalidEnumArgumentException(name, valueInt32, enumType); } } } public static void ArgumentOutOfRangeCheck(T value, string name, T minValue, T maxValue) where T : IComparable { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentIncompatibleTypeCheck(minValue, "minValue", typeof(T)); ArgumentValidation.ArgumentIncompatibleTypeCheck(maxValue, "maxValue", typeof(T)); if (value.CompareTo(minValue) < 0 || 0 < value.CompareTo(maxValue)) { throw new ArgumentOutOfRangeException(name, value , string.Format("Argument {0}must be greater than or equal to {1} and less than or equal to {2}." , ArgumentValidation.PadWord(name), minValue, maxValue)); } } public static void ArgumentOutOfRangeExclusiveCheck (T value, string name, T lowerBound, T upperBound) where T : IComparable { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentDifferentTypeCheck(lowerBound, "lowerBound", typeof(T)); ArgumentValidation.ArgumentDifferentTypeCheck(upperBound, "upperBound", typeof(T)); if (lowerBound.CompareTo(upperBound) == 0) { throw new ArgumentException("Arguments lowerBound and upperBound cannot be equal."); } if (value.CompareTo(lowerBound) <= 0 || 0 <= value.CompareTo(upperBound)) { throw new ArgumentOutOfRangeException(name, value, string.Format("Argument {0}must be greater than {1} and less than {2}." , ArgumentValidation.PadWord(name), lowerBound, upperBound)); } } public static void ArgumentOutOfRangeIncludeMaxCheck (T value, string name, T lowerBound, T maxValue) where T : IComparable { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentIncompatibleTypeCheck(lowerBound, "lowerBound", typeof(T)); ArgumentValidation.ArgumentIncompatibleTypeCheck(maxValue, "maxValue", typeof(T)); if (value.CompareTo(lowerBound) <= 0 || 0 < value.CompareTo(maxValue)) { throw new ArgumentOutOfRangeException(name, value, string.Format("Argument {0}must be greater than {1} and less than or equal to {2}." , ArgumentValidation.PadWord(name), lowerBound, maxValue)); } } public static void ArgumentOutOfRangeIncludeMinCheck (T value, string name, T minValue, T upperBound) where T : IComparable { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentIncompatibleTypeCheck(minValue, "minValue", typeof(T)); ArgumentValidation.ArgumentIncompatibleTypeCheck(upperBound, "upperBound", typeof(T)); if (value.CompareTo(minValue) < 0 || 0 <= value.CompareTo(upperBound)) { throw new ArgumentOutOfRangeException(name, value, string.Format("Argument {0}must be greater than or equal to {1} and less than {2}." , ArgumentValidation.PadWord(name), minValue, upperBound)); } } } }
Posted by IDisposable at 1/17/2006 12:08:00 PM 3 comments
Labels: .Net, C#, generic, validation
When doing code generation using CodeDom, you often need to emit things that are easily expressed in C# or other high-level languages. These patterns (like a using
block, or an event
subscription) are ideal candidates for a helper-class to regularize the emission. Luckily, Omer van Kloeten has done the work for us, enjoy Commonly Used .NET Coding Patterns in CodeDom found over at The Code Project
Posted by IDisposable at 1/16/2006 12:13:00 PM 0 comments
Are you having trouble with User Instance databases with SQLExpress 2005? Sometimes they don't seem to start right, especially when using RDP to connect to a developmnet machine (even to a VirtualPC instance)? Guess what? It's a Microsoft bug. Here's the hotfix. You cannot connect to Visual Studio SQL Server Express on a remote Windows XP Service Pack 2-based computer
Posted by IDisposable at 1/10/2006 01:00:00 AM 0 comments