 Saturday, August 09, 2008
Isolated Storage
In my last post, I showed how to write stuff out to a temporary directory. After I wrote the post, I started thinking about how people could misconstrue the meaning of it. The post was intended to show how to dump stuff easily to a random directory on the file system. The code that drove me to write that particular example came from a unit test that was using the temporary directory as a repository for the output of the XmlSerializer. In other words, I really was not doing anything meaningful with the data. To clear things up, I thought I would write a post that showed how use a unknown storage directory as a meaningful repository for application data. What constitutes meaningful data? I don't know, it's your app!!! But common possibilities include application settings, user-specific data, etc... I'm thinking of things that might be otherwise be stored in the registry. Yeah, don't do that anymore. I don't know about you, but the just the word "registry" causes me to shudder. .Net has introduced a new concept called "Isolated Storage" to hold this type of information. Isolated storage is an unspecified location on the file system that is hidden away from the application. Even though the location is unknown, the application is guaranteed to have full permissions to it, even if it is running in a restricted security mode. As it name implies, the location is "isolated" so that any data written to it does not affect other applications or anything else on the file system. So as far as security goes, you're limited to only hurting yourself by maliciously or ignorantly (mis)using this repository. Here's a code sample of how you would use it to store data: // get the location specific to this user/assembly
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForAssembly();
// create a file to write the data to
using ( var outStream = new IsolatedStorageFileStream("foo.txt", FileMode.Create, isf) )
{
using ( var sw = new StreamWriter(outStream) )
{
// write out the text
sw.Write("Random text");
sw.Close();
}
}
And here is how you can retrieve it: IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForAssembly();
// open the file
using ( var inStream = new IsolatedStorageFileStream("foo.txt", FileMode.Open, isf) )
{
string[] files = isf.GetFileNames("foo.txt");
if ( files.length > 0 )
{
StringBuilder sb = new StringBuilder();
foreach ( var file in files )
{
using ( var sr = new StreamReader(inStream) )
{
sb.AppendLine(sr.ReadLine());
}
}
}
}
This method is a much more "enterprise-y" way to access data in your applications.
Saturday, August 09, 2008 3:45:26 PM (Eastern Standard Time, UTC-05:00) .Net | C#
 Friday, August 08, 2008
Using Temp directories in .Net
Have you ever found the need to use a temporary directory on the file system in your code? This issue came up with me recently (and bit me in the ass), so I thought I would share some experiences on how I overcame the problem. At the root of the problem is that you need some sort of permanent storage, but nothing that is stringent enough to require it reside in some "known" directory where it can be accessed at a later time. You don't really care where you store a file, but you need to store it somewhere. I recently came across a piece of code in a unit test that serialized a class using the XmlSerializer. The person who wrote the test must have wanted to see what the class looked like in serialized form. The code was written so that the xml version of the class was dumped to the file system. However, when the test was written, the file was hard-coded to the C:\Temp directory. As part of my task, I was incorporating the unit tests on this component into the continuous build. Guess what happened when the test was moved the build server? FAIL!!! No C:\Temp directory on that machine means lots of red on the build server and the IT director screaming WTF?!?!? The lesson is, never make assumptions when accessing the file system. In this case, the test was counting on the directory both existing and the user having permissions to it. Obviously, that's not a good idea. There are other ways to get to a valid "temporary" directory in .Net. The following code sample shows how you can try a few known places in .Net that should work as "temporary" directories. /// <summary>
/// Get a valid "temporary" directory on the machine that is running this code
/// </summary>
/// <returns>a temporary directory</returns>
private string GetTemporaryDirectory()
{
// try this first
string dir = Path.GetTempPath();
if ( String.IsNullOrEmpty(dir) || !Directory.Exists(dir) )
{
// see if the "TEMP" environment variable is set
dir = Environment.GetEnvironmentVariable("TEMP");
if ( String.IsNullOrEmpty(dir) || !Directory.Exists(dir) )
{
// hmmm ... let's create one in "My Documents"
string myDocsDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
if ( String.IsNullOrEmpty(myDocsDir) || !Directory.Exists(myDocsDir) )
{
// no "My Documents" directory???
throw new Exception(
"Cannot determine a valid temporary directory on this system. " +
"Please set a valid directory for the \"TEMP\" environment variable.");
}
dir = String.Format("{0}\\Temp", myDocsDir);
if ( !Directory.Exists(dir) )
{
Log.Info("Creating new Temp directory in {0}", myDocsDir);
Directory.CreateDirectory(dir);
}
}
}
if ( dir.EndsWith("\\") )
{
// cut the last char off
dir = dir.Substring(0, dir.Length - 1);
}
return dir;
}
The code example above tries to use the .Net libraries to query the file system for some well-known directories that can be used for temporary files. If a valid one is not found, it will try to create a "Temp" directory in the current user's "My Documents" directory. At worst, the user should have access to this directory, and the build should not break based on a hard-coded assumption.
Friday, August 08, 2008 12:46:30 AM (Eastern Standard Time, UTC-05:00) .Net | C#
 Saturday, July 19, 2008
Don't call virtual methods in a constructor
I ran into a piece of code today similar to this: public class Base
{
public Base()
{
this.Initialize();
}
protected virtual void Initialize()
{
Debug.WriteLine("Base.Initialize()");
}
}
public class Derived : Base
{
public Derived() : base() {}
protected override void Initialize()
{
base.Initialize();
}
}
public class FurtherDerived : Derived
{
public FurtherDerived() : base() {}
protected override void Initialize()
{
Debug.WriteLine("FurtherDerived.Initialize()");
}
}
public class Tester
{
public static void Main(string[] args)
{
Base myBase = new Base();
Derived myDerived = new Derived();
FurtherDerived myFurtherDerived = new FurtherDerived();
Console.ReadLine();
}
}
See any problems here? Even though the compiler lets you call virtual methods from a base constructor, it's generally a "bad idea". That's because the constructor in the derived classes defers its construction up to its base classes before it executes its own constructor (even if we don't explicitly call the base constructor like in the example). Yet the call to a virtual function in the base class constructor is executed in the derived class implementation. This can cause subtle, unexpected problems.
In the example above, things "happen" to go well. It actually runs just fine. It outputs the following as you'd probably expect: Base.Initialize()
Base.Initialize()
FurtherDerived.Initialize()
But that's only because we didn't do anything significant in the derived constructors. What happens if we change the FurtherDerived class: public class FurtherDerived : Derived
{
StringBuilder _sb;
public FurtherDerived() : base()
{
_sb = new StringBuilder();
}
protected override void Initialize()
{
_sb.Append("FurtherDerived.Initialize()");
Debug.WriteLine(_sb.ToString());
}
}
Guess what happens when we run this code? FAIL!!! The dreaded, "Object reference not set to a reference of an object". Since the Initialize() method in the FurtherDerived class is called from the Base constructor, we are trying to access the _sb class level parameter before it's ever initialized. We are calling a method on an class we know has not been fully constructed. That ain't good.
The lesson is - never call a virtual method from a constructor. At best, you are introducing a bug waiting to happen. At worst, you've already done so.
Friday, July 18, 2008 11:57:17 PM (Eastern Standard Time, UTC-05:00) .Net | Back To Basics | C#
 Sunday, June 22, 2008
Enforce non-instantiability on static classes
Every project ends up with one or even possibly many static helper classes. If you program in Java, I'm willing to bet the house your project has a StringUtil class lurking around somewhere. These classes are easily abused, but can serve a valid purpose, such as a factory class responsible for creating instances. If these classes contain only static methods (as they usually do), there is never any reason for them to to be instantiated. However, in both Java and C#, it's easy to forget that if you do not explicitly declare a constructor, the compiler will generate a no-arg constructor by default. The consequence is that the following code is valid: StringUtil util = new StringUtil();
You've just allocated memory unnecessarily. Plus, the garbage collector will now incur extra overhead since it will have to reclaim this memory even though it was never actually used. All of the methods are static, so there is no reason to instantiate an individual object from this class.
To avoid instantiations, make sure you declare a private no-arg constructor. This will cause the compiler to throw an error any time the class is attempted to be instantiated. public class StringUtil
{
// constructor marked private since all methods are static
private StringUtil() {}
// bunch of static methods not shown
}
A side note - If you are using C# 3.0, I recommend using extension methods to enhance the behavior of existing classes rather than creating a something like a dedicated StringUtil class. First of all, any class declaring extension methods has to be marked as static and cannot be instantiated. And more importantly, it provides a much cleaner implementation to add those helper methods directly on the affected class. The added bonus is that Visual Studio is smart enough to provide Intellisense for extension methods on targeted classes.
Sunday, June 22, 2008 9:35:25 PM (Eastern Standard Time, UTC-05:00) Back To Basics | C# | Java | Programming
 Saturday, June 14, 2008
Collection Initializers
Scripting languages like Ruby and Groovy recognize the importance of collections like lists and maps, treating them almost like first class objects. By doing so, they make it really easy to create collections like these and populate them all in one step. For example, in Ruby here is how this is done: # create a list
lst = [1, 2, 3, 4, 5]
# create a map
map = { "one" => 1, "two" => 2, "three" => 3 }
Not surprisingly, we see very similar syntax in Groovy... // create a list
def lst = [1, 2, 3, 4, 5]
// create a map
def map = ["one":1, "two":2, "three":3]
And in case you missed it, one of the changes in C# 3.0 was the ability to initialize collections similar to the way it's done in these scripting languages (though the syntax is not *quite* as clean): // create a list
var lst = new List<int> { 1, 2, 3, 4, 5 };
// create a map
var map = new Dictionary<string, int> { {"one", 1}, {"two", 2}, {"three", 3} };
IMO, the new collection initializers (along with property initializers) are one of the nicest changes in the new version of the .Net framework. And since I'm feeling nice, I won't show how this is accomplished in native Java. 
Saturday, June 14, 2008 8:23:10 PM (Eastern Standard Time, UTC-05:00) C# | Groovy | Ruby
 Friday, May 30, 2008
New release of Miado
This new release contains significant changes. First and foremost, all the implementation classes have had their public scope removed, so you will now have to program exclusively against the interfaces. I have also moved the IMiadoDao interface to IMiadoRepository in order to encourage composition and not force an inheritance hierarchy. Combined with that change, I also moved the functionality from SimpleSql into IMiadoRepository, as well as making that interface the point where you access an IDbStatement, making the IMiadoRepository the main worker module of Miado. Another change is that you need to use the MiadoRepositoryFactory to create an instance of the IMiadoRepository. Enough with the talk, let's see some code... public AdddressDao { private static readonly string INSERT_ADDRESS_SQL = "insert into Address(Address1, Address2, City, State, ZipCode) " + "values(@Addr1, @Addr2, @City, @State, @ZipCode)"; private static readonly string SELECT_ADDRESS_SQL = "select AddressId, Address1, Address2, City, " + "State, ZipCode " + "from Address "; private static readonly string SELECT_ADDRESS_BY_ID = SELECT_ADDRESS_SQL + "where AddressId = @Id "; private static readonly string SELECT_ADDRESS_BY_ZIP_CODE = SELECT_ADDRESS_SQL + "where ZipCode = @ZipCode "; private static readonly string SELECT_COUNT_BY_STATE = "select count(*) from Address where State = @State ";
// uses MiadoRepositoryFactory.CreateMiadoRepository() public AddressDao() : this(MiadoRepositoryFactory.CreateMiadoRepository( SqlClientFactory.Instance, ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString)) {}
public AdddressDao(IMiadoRepository repository) { this.MiadoRepository = repository; } protected IMiadoRepository MiadoRepository { get; set; } public void SaveAddress(Address addr) { // uses SQL right in IMiadoRepository this.MiadoRepository .ExecuteNonQuery(INSERT_ADDRESS_SQL, addr.Address1, addr.Address2, addr.City, addr.State, addr.ZipCode) } public ICollection<Address> FindAddressesByZipCode(string zipCode) { // build IDbStatement and do the mapping in a lambda expression ICollection<Address> addresses = this.MiadoRepository .CreateDbStatement(SELECT_ADDRESS_BY_ZIP_CODE) .AddParameter("ZipCode", zipCode) .QueryForResults<Address>( row => new Address() { AddressId = row.GetValue<int>("AddressId"), Address1 = row.GetValue<string>("Address1"), Address2 = row.GetValue<string>("Address2"), City = row.GetValue<string>("City"), State = row.GetValue<string>("State"), ZipCode = row.GetValue<string>("ZipCode") }); return addresses; } public Address LoadAddress(int addrId) { // uses delegate method to do the mapping return this.MiadoRepository .CreateDbStatement(SELECT_ADDRESS_BY_ID) .AddParameter("Id", addrId) .QueryForOne<Address>(CreateAddress); } public int FindCountByState(string state) { return this.MiadoRepository .CreateDbStatement(SELECT_COUNT_BY_STATE) .AddParameter("State", state) .QueryForOne<int>(row => row.GetValue<int>(0)); } private static Address CreateAddress(IResultSetRow row) { return new Address() { AddressId = row.GetValue<int>("AddressId"), Address1 = row.GetValue<string>("Address1"), Address2 = row.GetValue<string>("Address2"), City = row.GetValue<string>("City"), State = row.GetValue<string>("State"), ZipCode = row.GetValue<string>("ZipCode") }; } }
Friday, May 30, 2008 10:57:03 PM (Eastern Standard Time, UTC-05:00) .Net | C# | Miado
 Wednesday, May 21, 2008
Using LINQ to generate a random confirmation number
Igor Ostrovsky recently published a great blog post about 7 tricks for using LINQ to simplify your programs. Posts like this really make me re-evaluate how I am writing my code in C# 3.0. For example, I had written a piece of code for my current project that generates a random confirmation number for a reservation system. After reading Igor's post, I built off one of his examples and refactored my code to use LINQ to build my confirmation number. I must admit, the refactored code is much more elegant:
private static readonly char[] AVAILABLE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890123456789".ToCharArray();
private static string GenerateConfirmationNumber(int length) { int lastIndex = AVAILABLE_CHARS.length - 1; Random rand = new Random(); var confNbr = Enumerable.Repeat<int>(0, length) // loop N times .Select<int, int>(loopNbr => rand.Next(0, lastIndex)) // get a random index .Select<int, char>(index => AVAILABLE_CHARS[index]) // pull a char .ToArray(); // project the results to a char[] return new String(confNbr); }
I think it's important to remember that LINQ is much, much more than just LINQ-to-SQL (which is what most people immediately think of when you refer to LINQ). In fact, none of the examples in Igor's post have anything to do with SQL. Take a look at his post (and other LINQ examples online) and hopefully it will give you ideas on how to code using more of a dynamic language type syntax.
Wednesday, May 21, 2008 9:42:57 AM (Eastern Standard Time, UTC-05:00) .Net | C# | Linq
 Wednesday, May 14, 2008
C# Extension Methods
In my last post, I showed an example of how you can create an extension method on an existing class in javascript. Well, C# 3.0 has now added the exact same functionality. And it just so happens that today I needed to create one, so I thought I would post an example of how it's done in C#.
public static class StringExtensions { public static byte[] ToByteArray(this string s) { return ASCIIEncoding.UTF8.GetBytes(s); } }
Extension methods act like static methods on existing classes, and as such they can only be declared in static classes. To mark a method as an extension method, you must preface the declaration of the first parameter in the method signature with the keyword "this". The compiler will then add the method to the type of class declared in the first parameter. Any other parameters declared after the first one will become the signature to the extension method.
Now we can call the extension method we added to the String class:
public class Program { public static void Main(string[] args) { string myString = "Foo"; byte[] bytes = myString.ToByteArray(); } }
The other cool thing is that Visual Studio provides full Intellisense on all extension methods! So in the example I provided, ToByteArray() is now offered up as a potential method anytime I reference a string.
Wednesday, May 14, 2008 12:43:26 AM (Eastern Standard Time, UTC-05:00) .Net | C#
|

Subscribe to this feed
 Email Me
 Follow Me On Twitter
| | Sun | Mon | Tue | Wed | Thu | Fri | Sat |
|---|
| 30 | 1 | 2 | 3 | 4 | 5 | 6 | | 7 | 8 | 9 | 10 | 11 | 12 | 13 | | 14 | 15 | 16 | 17 | 18 | 19 | 20 | | 21 | 22 | 23 | 24 | 25 | 26 | 27 | | 28 | 29 | 30 | 31 | 1 | 2 | 3 | | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
Search
Navigation
Tag Cloud
Archive
Blogroll
|