Thursday, October 29, 2009

Scary Halloween-Style C# 4.0 Code

Check out the following code:

using System;
using System.Dynamic;

namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
dynamic d = new ExpandoObject();
d.Hola = "Howdy";
SaySomething(d);
}

void SaySomething(dynamic d)
{
Console.WriteLine(d.Hola);
}
}
}

What do you think this code should do? There's no static method to accept the incoming parameter, so compile error, right?

Wrong.

This compiles, but blows up at runtime with a RuntimeBinderException, not finding the instance method SaySomething.



While the above compiles just fine, the following does not:

using System;
using System.Dynamic;

namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
dynamic d = new ExpandoObject();
d.Hola = "Howdy";
SaySomething(d);
}
}
}

Rightly recognizing that SaySomething doesn't exist in the current context.

This is the scariest thing I've seen all week. And I was in Austin last weekend.

So why does it do this? This goes back to the way that overload resolution is achieved during compilation. Eric Lippert wrote about this problem in C# 3.0 earlier this year. Overload resolution steps (for C# 3.0) are as follows, in this order:

1. First, each overload is examined according to it's arguments.
2. Next the determination of whether or not the overload is accessible from the current static or instance context is made.
3. If the overload selected from step 1 is inaccessible, then a compile-time error is thrown.

Now, let's look at the situation I posed above. The major difference here is when this resolution occurs. The first example actually compiles, because the overload resolution is delayed until runtime. The order of operations, however, stays the same.

At runtime, these steps are performed in the following order:

1. First, each overload is examined according to it's arguments.
2. Next the determination of whether or not the overload is accessible from the current static or instance context is made.
3. If the overload selected from step 1 is inaccessible, then a run-time error is thrown.

In other words, the rules are exactly the same as they were in C# 3.0, but the consequences of this mistake while using dynamic are much more severe than they are when not using the dynamic type.

All this to say, the dynamic type is a nice addition to the C# toolbox, but it needs to be used with extreme care.

With great power comes great responsibility.

Monday, October 26, 2009

A Better Developer

We developers are constantly barraged with an overflow of activities and information we don't possibly have enough time for, and we're given very little guidance on what is and isn't worthwhile. This morning on my drive to work, I was reflecting on some of the things I'm involved with, questioning the usefulness of each. Some of these activities (other than the act of coding itself) include:
  • Using Twitter
  • Attending User Groups
  • Leading User Groups
  • Attending Conferences
  • Speaking at Conferences
  • Reading Books (of various kinds)
  • Writing Books
  • Participating in IRC
  • Contributing to Open-Source Projects
  • Taking Certification Tests
  • Contributing to Forums
  • Writing Blogs
  • Reading Blogs
  • LinkedIn
And that's just to name a few.

Which ones are and aren't worthwhile to you is wholly dependent on your personality, affinity, and general life direction.

There's a peer-pressure that comes with this (or any) industry to be noticed, but ultimately, the question we, as developers, should all be asking is "does this make me a better developer?" Answer that question, and you'll know what's worth giving your time to.

Wednesday, October 21, 2009

Adventures in Office Interop and C# 4.0

I had a chance earlier to play with the new features introduced to C# 4.0 for the support of Office Interop. There are a couple of notable features.

First, Type.Missing is no longer required to pass into COM calls. This means no more:

wbs.Open(@"somefile.xlsx", missing, missing, missing, 
missing, missing, missing,
missing, missing, missing,
missing, missing, missing,
missing, missing);

Instead you can opt for:

wbs.Open(@"somefile.xlsx");

Readability FTW!

Other changes include the ability to use the indexed methods ("get_Range" for example) using indexers. Now, instead of:

Range range = ws.get_Range("A1", "A1");

You can use:

Range range = ws.Range["A1"];

Combined with the optional parameters, this makes for another win for readability.

In some situations, this "inferred property" addition makes things even more readable. How many times when setting a value in Excel Interop have you done this:

range.set_Value(XlRangeValueDataType.xlRangeValueDefault, i);

Yeah, not too pretty. Try this on instead:

range.Value = i;

Uh-huh. Yep. Much, much more readable.

That is all.

Monday, October 19, 2009

Be a Better Polyglot with F#'s CompiledNameAttribute

F# introduces the CompiledNameAttribute with the October 2009 CTP. This attribute provides a way to specify the compiled name of a method or type written in F#. The big advantage here is the ability to prevent having to compromise on your naming schemes in either F# or any other language. Internally to the assembly, you can still use the names you give to the constructs when you define the construct. Externally, however, the name will be compiled into a ".NET Friendly" name, which you can specify using the CompiledNameAttribute.

Take, for example, the extension method I wrote in my previous post. Using the CompiledNameAttribute, I can refer to this in F# using one name, and in C# using another name.

[<System.Runtime.CompilerServices.ExtensionAttribute>]
module public Morton.Extensions.EnumerableExtensions
[<Microsoft.FSharp.Core.CompiledNameAttribute("OutputAll")>]
[<System.Runtime.CompilerServices.ExtensionAttribute>]
let internalNameGoesHereForOutputting (_this:System.Collections.Generic.IEnumerable<'T>) =
for x in _this do System.Console.WriteLine x |> ignore


Note the internal name here is "internalNameGoesHereForOutputting" while the external name will be "OutputAll".

This is a very nice feature indeed, and I'd love to see it implemented in other languages as well. Kudos to Don Syme and the rest of the F# team for this one. This is an excellent step towards polyglot programming: translation.

Writing Extension Methods in F# to Use in C#

F#, in my mind, is the language of implementation. It provides a concise syntax when writing code "in the small" that is in many ways superior to C#. This makes F# the ideal language for writing extension methods and other methods that perform operations that are frequently repeated.

Here's a small example on how to write an extension method in F# that takes a generic IEnumerable<T> and outputs each value to the console:

[<System.Runtime.CompilerServices.ExtensionAttribute>]
module public Morton.Extensions.EnumerableExtensions
[<System.Runtime.CompilerServices.ExtensionAttribute>]
let OutputAll (_this:System.Collections.Generic.IEnumerable<'T>) =
for x in _this do System.Console.WriteLine x |> ignore

Note the use of the ExtensionAttribute on both the module declaration and on the function declaration. Both of these are necessary to create the extension method.

In C#, this code could be called just like any other Extension method. First, add the proper using statements to your code, then call the method from any applicable type.

The following code compiles and works properly when referencing an F# assembly containing the above function:

using System.Collections.Generic;
using Morton.Extensions;

namespace ConsoleApplication1
{
static class Program
{
static void Main(string[] args)
{
List<string> list = new List<string>();
list.Add("David");
list.Add("Jennifer");
list.OutputAll();
}
}
}


Now we're cooking. I could see myself using F# for tons of utility methods where writing it in C# would simply be too cumbersome.

UPDATE (10/30/2009)

I received a question today asking how these extensions could also be used from F# as well, with the same syntax. It's not too difficult, but it does require a tiny bit of additional work. The final code would look something like this:

[<System.Runtime.CompilerServices.ExtensionAttribute>]
module public Morton.Extensions.EnumerableExtensions
[<System.Runtime.CompilerServices.ExtensionAttribute>]
let OutputAll (_this:System.Collections.Generic.IEnumerable<'T>) =
for x in _this do System.Console.WriteLine x |> ignore

type System.Collections.Generic.IEnumerable<'T> with
member this.OutputAll() = this |> OutputAll

Monday, October 12, 2009

On Teachability in Team Development

EDIT: Note that the terms "architect" and "developer" below are used loosely. This post deals most directly with the teachability of a specific team member, whether that team member is an architect, developer, tester, etc. This post assumes that the teacher, regardless of his role, is competent in teaching. The architect/developer dichotomy below is use purely as a convenience to the purpose of the post.

Software craftsmanship is more than just a set of intellectual know-how. Character traits also affect your ability to do the job. The biggest barrier I see to excellent programming is often a lack of teachability. It doesn't matter how smooth the software architecture is; if the developer can't or won't learn the architecture, it's of no use - the architecture will go by the wayside.

So in that vein, here are the top few barriers to teachability that I've seen:

Arrogance - The arrogant developer always has a better way, and his way is never wrong. He'll fail to be teachable, because he already believes he knows it all. According to him, his code is perfect, so he spends most of his time blaming others or outside factors for bugs that show up. He'll never implement an architecture properly, because the architecture, in his opinion, is not as good as he could have made it. Sadly, the arrogant developer was teachable at one point, but his success made him arrogant and he lost his ability to learn.

Laziness - A certain amount of laziness is a wonderful trait for a developer to have. It's this laziness that makes a developer say "There's gotta be a better way". Unbridled laziness, however, ignores the architecture "because it's too much work". It's not that he can't learn it, it's that he doesn't want to, and ugly code ensues.

Ability - Sadly, through no fault of their own, there are those developers that simply lack the ability to think logically, which is a needed trait for a developer. I don't believe that anyone can program, just as I don't believe that everyone can sell or perform scientific research or manage people. Different people have different strengths. Typically people who are not teachable in one thing are often teachable in another. These people should be encouraged to find those areas in which they excel. Luckily, these people are typically filtered out early on.

Apathy - This is related to laziness, but this developer isn't lazy - he's tired. He may be worn out on a particular project or with a particular technology, and he just doesn't care enough anymore to implement excellence.

In any of these situations, it's important to keep the team fresh. An infusion of new blood can often help to renew the team and make it into something vibrant again.

Friday, October 9, 2009

Closures in C#

LINQ has alot of "gotchas". Take the following code, for example:

using System;

namespace ConsoleApplication50
{
class Program
{
static void Main(string[] args)
{
int value = 100;
Action<int> curriedAction =
x => Console.WriteLine(x * value);
curriedAction(5);
}
}
}

How does C# handle closures? Let's take a closer look. Here's the IL for the Main method:

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 3
.locals init (
[0] class ConsoleApplication50.Program/<>c__DisplayClass1 CS$<>8__locals2)
L_0000: newobj instance void ConsoleApplication50.Program/<>c__DisplayClass1::.ctor()
L_0005: stloc.0
L_0006: ldloc.0
L_0007: ldc.i4.s 100
L_0009: stfld int32 ConsoleApplication50.Program/<>c__DisplayClass1::value
L_000e: ldloc.0
L_000f: ldftn instance void ConsoleApplication50.Program/<>c__DisplayClass1::<Main>b__0(int32)
L_0015: newobj instance void [mscorlib]System.Action`1<int32>::.ctor(object, native int)
L_001a: pop
L_001b: ldloc.0
L_001c: ldc.i4 200
L_0021: stfld int32 ConsoleApplication50.Program/<>c__DisplayClass1::value
L_0026: ret
}

Look at the locals declaration:
 .locals init (
[0] class ConsoleApplication50.Program/<>c__DisplayClass1 CS$<>8__locals2)

Looks like there's a whole lot more happening here than I originally intended. Instead of having a local integer variable, I'm spinning up a whole class simply to hold my single integer variable. In fact, there is no local integer variable in this method. It's this local <>c_DisplayClass1 instance that actually hosts the integer within it.

Also contained within this DisplayClass1 class is my delegate, which isn't just a static method at this point, it's an instance method.

public void <Main>b__0(int x)
{
Console.WriteLine((int) (x * this.value));
}

Interestingly, you can even view the variable for the target by calling the Target property of the curriedAction variable. If I add the following two lines to this method:

var target = curriedAction.Target;
Console.WriteLine(curriedAction.Target);
Console.WriteLine(target.GetType().GetField("value").GetValue(target));

I get this as part of the output:
ConsoleApplication50.Program+<>__DisplayClass1
100

So it appears that in situations where there is no closure, the compiler favors a static method, and in situations where there is a closure, the compiler favors an instance method on a compiler-generated class.

I've heard people complain about LINQ's performance versus a for or a foreach loop, and I wouldn't be surprised if this has something to do with it. Remember, each instantiated class will have to be collected at some point. All in all, I'd say to avoid using closures wherever possible whenever performance is an issue.

Thursday, October 8, 2009

User Interface Basics: Don't Taunt Your Users

The setup was taking a while so I moved on to other things. Which button do you think I wanted to press?

Wednesday, October 7, 2009

Covariance and the "ref" Keyword.

Here's a slight little detail worth noting.

If you're passing a value into a method that uses the "ref" keyword, the type of the variable passed must match the ref parameter exactly.

The value passed into the ref method is reassigned upon the method's completion, so the object reassigned must match the variable's declared type. If a variable's type is only derived from the parameter type requested by the method, there would be nothing stopping the method from reassigning the ref parameter internally thus causing a type mismatch on the method's completion.

Monday, October 5, 2009

On Blogging

I find my Google Reader queue fills up very quickly, and it's a rare situation in which I'm actually interested in reading most of the blogs I've added there. I find myself repeatedly attracted to the non-technical blogs, such as Seth Godin's blog. In all honesty, the technical blogs bore me after a while. I suppose my thought process goes something like this: "If I don't need to know about something right now, then why am I spending my time reading it?"

I think both are important, but I'm beginning to think that the technical blogs are good material for search engines, while the non-technical ones are the ones I really want to read on a daily basis. I only read the technical ones when I'm trying to figure out the details on exactly how to perform a task, while the non-technical ones really encourage me towards excellence in my craft.

I'm curious to know how many of you would say the majority of the blogs you follow are highly technical, and how many are less technical, but no less relevant, being applicable to more general aspects of your job.

Wednesday, September 9, 2009

Windows Internals Review - Part 1

I know I've been a bit "radio silent" lately. I've been reading through Windows Internals by Russinovich and Solomon, for a review I'm doing for Microsoft Press. I'm pleased to say that the first part of this review is up now on the Microsoft Press Blog, and you can read it here. Over the next couple of months, I anticipate that the majority of my time spent outside of work will be spent reading this particular book and working on subsequent reviews of it. It's an excellent book, and I'm learning a tremendous amount of information from it. If you're even slightly interested in what goes on behind the scenes in Windows, I would highly recommend this book.

Monday, August 31, 2009

On the Evils of ObjectContainerDataSource with MVP Pattern

Oh my head is hurting after banging it against the wall for a while now. I've been working with the Web Client Software Factory, and started using the ObjectContainerDataSource class to try to bind some of our model to the view. All was going well, until I found the fine print from the How to page on the ObjectContainerDataSource. That's when I started becoming very angry.

Here's the fine print:

Instance. This is the data object. The ObjectContainerDataSource control uses reflection to create this object (on every update operation, delete operation, and insert operation) and populates it with the input data from the data-bound control.


Huh?

Why on this green ball on which I sit would I want a reconstituted object populated with only the data that was bound to the form?

Don't they understand that there might be more data here I want to maintain? The issue, as far as I can tell, is that the MVP pattern is expecting that the object you bind to the UI will have absolutely nothing but the specific properties that show up on a FormView. This isn't true. I might want to reuse the same object (staying DRY and enabling object reuse. Somehow, I gotta use the same object, so I have a few options:

1. When I hit the point of updating the object, ignore the instance that the ObjectContainerDataSource creates, and simply fetch the old object from the services, checking each property (perhaps via reflection) and setting the properties that have changed onto the object in question. This is obviously a bad idea for several reasons. First of all, that means I'm going to have to make another call to the database, adding more time to the update. I don't want to do that. Also, I'm going to have to write some funky reflection code to compare all the values. This is more work than it's worth.

2. Store the object in state, and retrieve it. That's a nice idea, but what if this whole MVP pattern is being implemented on a user control and I'm planning on having more than one of these controls on a specific page? That won't work either, as the instances will overwrite one another.

3. Completely and totally override the ObjectContainerDataSource and ObjectContainerDataSourceView and make a new one. One desperate programmer has already tried this and I nearly did too, but I felt the solution was a little bit bloated for my needs. Again. I'm lazy.

4. Drop the whole thing, fetch the items from the database, and manually set the value from each and every field in the FormView to the object. Nah. Not gonna do that.

So what was the solution I came up with? I'm sure most of you are hanging on the edge of your seats with bated breath.

I ignored the entire Updated event entirely.

Here's why. The Updated Event comes with the ObjectContainerDataSourceStatusEventArgsobject, while the Updating event comes with the ObjectContainerDataSourceUpdatingEventArgs object, both of which would make Steve McConnell choke because of their names. Nevertheless, they're very different objects.

The ObjectContainerDataSourceStatusEventArgs provides two properties: Instance, and AffectedRows. Instance is the reconstituted (regurgitated?) version of the bound object, while AffectedRows tells you how many fields the user changed before he/she submitted. Yeah, both of those are pretty useless.

Contrast that with the Updating event. The Updating event offers you the Keys property, and the NewValues and OldValues Dictionaries, along with the Cancel property to cancel the update altogether. Ahh, now we can determine exactly what's changed.

Now, buried deep in the framework is a type I found while hunting around called the
TypeDescriptionHelper. This class is the right to ObjectContainerDataSource's wrong.

On TypeDescriptionHelper, there's a poorly named, but very useful method called BuildInstance, which takes an IDictionary and an existing instance of the bound class. It reflects on the bound class and sets the values as indicated in the dictionary you pass in. This method is actually called after the Updating event, but before the Updated event, after ObjectContainerDataSourceView calls Activator.CreateInstance to create an instance of the class you've bound to the form. The only difference is, we're going to call it here.

So what I chose to do is narrow the dictionary down to only those values that have changed, by comparing the OldValues with the NewValues, and then pass the resulting dictionary to the BuildInstance method along with the Person, which, believe it or not, I can get by casting the sender to ObjectContainerDataSourceView, and pulling it out of the Items collection. My final method looks like this:


protected void UpdatingPerson(object sender, ObjectContainerDataSourceUpdatingEventArgs e)
{

var source = sender as ObjectContainerDataSourceView;
var person = source.Items[0] as Person;

Dictionary<string, string> changedValues = new Dictionary<string, string>();

foreach (string key in e.Keys)
{
if (!e.OldValues[key].Equals(e.NewValues[key]))
changedValues.Add(key, e.NewValues[key] as string);
}

TypeDescriptionHelper.BuildInstance(changedValues, person);

_presenter.SavePerson(person);
}


This UpdatingPerson method is the handler for the ObjectContainerDataSource's Updating event, and I don't handle the Updated event at all.

Another advantage to this method is the fact that I'm not setting anything that hasn't changed. I leave all the other properties alone. As they should be.

Friday, August 28, 2009

BinaryFormatter: Fields, Properties or Both?

I ran into the second person today who was confused on this concept, so I thought I'd post the answer here. For those of you who missed the question it is: "When I serialize an object, does it only serialize properties, or does it serialize the fields also?".

Well, the answer depends on how you serialize the object. For this post, I'm only going to talk about the BinaryFormatter. XmlSerializer and DataContractSerializer both work differently, reflecting on properties (for XmlSerializer) or properties and fields (for DataContractSerializer). Properties serialized with either the XmlSerializer or the DataContractSerializer will actually call any logic within the properties they're setting. Binary formatter does not. Here's some example code to prove that BinaryFormatter will leave your properties alone:


using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace ConsoleApplication31
{
internal class Program
{
private static void Main()
{
// create an instance of the object
var thing = new StrangeThing();

// set the value.
thing.SetValue(5);
Console.WriteLine("Initial value is {0}", thing.Value);

// serialize our object.
var formatter = new BinaryFormatter();
var stream = new MemoryStream();
formatter.Serialize(stream, thing);
stream.Position = 0;

// Deserialize the object. If this is calling setters, it should throw.
var thing2 = (StrangeThing) formatter.Deserialize(stream);

// Output the result.
Console.WriteLine("After deserialization, the value is {0}", thing2.Value);
Console.WriteLine("Setter was never called");
}
}

[Serializable]
internal class StrangeThing
{
private int _value;

public int Value
{
get { return _value; }
// make the setter throw.
set { throw new NotImplementedException(); }
}

// another method to allow us to set the value.
public void SetValue(int value)
{
_value = value;
}
}
}


The binary formatter establishes the actual "binary" representation of the object. The assumption with binary formatter is that, if the fields are all serialized, the properties will work as expected, because properties are nothing but fancy methods, basically. Thus, the BinaryFormatter only serializes fields, and never properties.

Incidentally, serializing only fields is a great way to make a DataContract in WCF. Should you desire, against my earlier admonitions never to make your business objects data contracts, at least do yourself a favor and never set your properties as DataMembers, only decorate the fields.

Wednesday, August 19, 2009

Understanding Escape Characters (For Beginners)

I had a question asked on the forum recently about escape characters, and since this is a rather frequent question for C# beginners, I've chosen to reproduce the material here. If you already understand escape characters in string literals, you can stop reading now.

Let's say that I have to write a computer program that reads a string character by character. I've decided that I need to use double quotes to signify the beginning and the end of a string. Knowing this, I can represent the string

bob

in my code file by typing:

"bob"

Great, no problem. But, what if I want to signify the following:

Bob says, "Hello."

Now I have a problem. The text I want to represent contains a quote character. So doing this won't work:

"Bob says, "Hello""

Because, the quote signifies the beginning and the ending of ths string. So what do I do? I use a special character that means "the next character should be considered part of the string, and not signify the beginning or the end of the string. I'll make that character be a "\". So now, I can type the following to represent my desired string:

"Bob says, \"Hello\""

Preceding the quote symbol with a backslash means that the next character is going to be a quote that is considered part of the string, not the end of the string. Not preceding it means that I'm signifying the end or beginning of the string.

Now that I've done that, I have another problem. What if I want to represent the escape character (the "\" character)? For example, what if I have a string like the following:

C:\Program Files\Morton\

Because I've redefined my backslash to mean that the next character is to be taken literally and not as a bounds to the value I'm trying to represent, how do I represent the "\" character itself?

To do this, I follow that backslash with another backslash to represent the end of the string. So now, to represent the string, I do this:

"C:\\Program Files\\Morton\\"

The above format is what the C# debugger will show when you hover over a particular string variable containing the text:

C:\Program Files\Morton\

In other words, it shows the value as it would need to be written in the source file, and not as it actually is.

So what about when you need to represent the following text:

When two backslashes (\\) are together, it means we want to represent a single "\" character.

How would you format that in the source code? Like this:

"When two backslashes (\\\\) are together, it means we want to represent a single \"\\\" character."

Confusing, I know, but the idea is still the same. My actual text I want to represent contains two backslashes in succession, so to represent that, I'd have to put four backslashes in succession. Also, note how the characters following "single" and before "character" are represented, by using a backslash, quote, backslash, backslash, backslash, quote respectively.

This is what it means to escape a string. Though string appear escaped in the debugger, this does not add to their length. The runtime still recognizes an escaped character as simply one character and not two. In other words, it does not take into account the escape character (\) when calculating the length of the escaped character (\\).

This is how C# regular literals are represented. This is needed in order to ensure that the compiler, which reads a string line by line, can understand the programmers intention, that they intend to enter a literal quote character versus simply ending the string. I hope this helps to understand the concept.

Tuesday, August 11, 2009

Houston F# Users Group - August 27th 7:00 PM

The Houston F# Users Group for August will be taking place August 27th at 7:00 PM in the Catapult Systems Training Room. We'll be having an interactive, hands-on session where we'll actually get to code some F#. All levels of knowledge are welcome, and there will be food!

Catapult Systems Houston
10370 Richmond Avenue
Suite 1250
Houston, TX 77042


View Larger Map

We're the building on the left lower corner of the map (the southwest most building on the north east corner of Richmond and Beltway 8) on the 12th floor.

See you then!

Tuesday, August 4, 2009

What is Code Quality Anyways?

Since I was young, my father has encouraged me to become a writer, so a few years ago, I entertained the idea, and bought a book by Stephen King called "On Writing". From it, I learned several aspects of good writing. One of the most memorable was to avoid adverbs ending in -ly. The reason they should be avoided is because your verbs, nouns and adjectives should describe your intentions without the use of adverbs. Adverbs are extra fluff, and when overused, are the mark of an immature writing style.

Until I read that book, I never thought about the importance of one sentence. A good novel writer ensures that his audience is not subjected to needless modifiers that serve to support poorly written sentences. Not only this, but he does it on a consistent basis, one sentence at a time, until the entire novel is written, all the while focusing on the overall plot of the book. The mark of quality in a novel is it's ability to move the plot forward while avoiding unnecessary distractions. This hallmark is established with each and every sentence.

In the publishing world, there are checks and balances to ensure that before a novel is released, the quality of the novel matches up to certain standards. After the novelist writes the novel, he sends the manuscript to the publisher, who typically suggests one or many edits that the manuscript needs before it's ready to be published. The novelist then edits his manuscript and repeats this process until the book is ready to publish.

Now, liken yourself to a novelist. You have a novel (your code) full of sentences (lines) that you're tasked to write. The assumption is that you will not only focus on the purpose of the application, but will also focus on how that purpose is to be achieved, by paying attention to each and every line of code. I've heard it said recently that "it only takes one line to create a dependency". This statement shows the power that one line of code can have. It can make or break your application.

So what is code quality? Quality code can only come from paying attention to each line you write. As I'm writing this blog, I'm paying attention to each and every sentence I write. I'm reviewing each one to verify they communicate my point clearly and concisely. The reason I'm doing this is because I know there are people who will read this post. They'll analyze what I'm saying, and won't want to waste their time while reading it. They expect to learn something from every sentence.

So why don't we do this as much in our code? I think it's because we believe that our code will never be read. It will only be used. This is a false assumption that needs rejecting. Every day I read the code I've read in order to modify it, or in order to hunt down a bug. The way the code is written is almost as important as what it does. Poorly written code takes longer to maintain. Well written code can be maintained almost effortlessly.

Each line of code should serve a purpose. Each set of lines should be reviewed as it's being written, to ensure the most clear and concise expression of the concept is found. Each architectural construct should be reviewed for it's flexibility and it's contribution to the overall goal. This should happen not in a designated refactoring session, but during the moment-by-moment process of coding.

This takes patience, consistency and the ability to clearly adhere to and express the purpose.

Code quality, in my definition, is a well-assembled collection of well-expressed lines of code, none of them being taken for granted. This is a basic concept, but one that needs reinforcing from time to time. There are so many concepts to quality programming that it takes a lifetime to master them all (if indeed they can be mastered), but for a good start allow me to suggest SOLID principles and design patterns. Professional programmers will learn these techniques and use them to their advantage. Poor programmers will abuse the code and muddle it's intentions.

Refactor in the small, and refactor consistently as you go. A good place to start might be to begin reading Sean Chambers' current blog series entitled 31 Days of Refactoring.

Learn these techniques and apply them as you go, not after the fact, and you'll find at the end that your code can be as enjoyable to read as some of the world's greatest authors, from Hemingway to King to Rowling.

Write code like it's going to be read.

Monday, August 3, 2009

The Wiki is Live

I've finally done it. For a while now I've been looking for a way to organize my thoughts efficiently and effectively, while actually retaining the things I'm learning. The wiki is designed to help with that, and I've been working on it for a couple of weeks now.

Generally I get my information from one of a few sources (in no particular order):

1. Daily life. I learn quite a bit just by programming.
2. Podcasts.
3. Online Forums (most notably the MSDN forums, where I contribute heavily)
4. Blogs I subscribe to.
5. Blog posts people send to me.
6. Talking with people older and more experienced than myself.

Sometimes, I find that while researching this information, there's bits and pieces of information I need in order to fully understand the information I'm looking at, so I'm making a commitment to actually follow these breadcrumb trails to better learn at least a little of the concepts and/or technologies that seem integral to the conversation at hand.

But this presents a problem. What pieces of information am I going to record? Certainly I don't have the time or patience to seek out a full understanding of everything, so I have to limit what information I seek out to the minimum, earmarking things I want to revisit, and remembering the chief point of the rabbit trail that led me to learn that bit of information I'm learning, so I can ultimately accomplish my goal.

The problem is this: I'll have several pieces of information unfinished.

The good news is this: That's the life of the developer, so I'm not alone.

We will never know everything about everything, so the best we can do is learn alot about a little, and the rest we might know a little about. I believe the Wiki expresses this sentiment. There are some things that I know little about, and don't need to know about in depth, so I don't go in depth. In fact, some of the wiki entries are single sentence entries, simply meant as stubs to be fleshed out at a later date, or in some cases, never. Nevertheless, I feel it's extremely important to document my journey, in an effort to help those who might come after me to learn from me some of the things I've learned.

So, after much introduction, allow me to introduce: Coding Light Wiki. Enjoy.

Saturday, August 1, 2009

New Name and Style (and Some Comments on Simplicity)

So I decided to shake things up a little bit... I've had this blog for over a year now, and this morning decided to edit the page... "a little". Well, that got blown to bits when I clicked "Save Template" on Blogger, thinking it would allow me to download and save my current template. "Save Template" actually means "apply the current template". Suddenly my whole blog's color scheme had changed, and I lost all my adjustments.

I also realized my label cloud was completely broken. That hurt me.

So began the metamorphosis. I started editing the templates and finally found a template I liked, and decided in the process to rename my blog to something a little more creative and descriptive than the previous name: David Morton.

I decided on Coding Light. The idea being that code should be light. There are so many "cool" things out there right now in shiny silver boxes, that it's easy to get stuck in the trap of thinking that the right combination of tools can effectively eliminate the difficulty and complexity in programming. Many tools exist for the sole purpose of flexibility. Bob Martin has astutely observed:

The cost of flexibility is complexity. Every time you put extra stuff into your code to make it more flexible, you are usually adding more complexity. If your guess about the flexibility needs of your software is correct, then you are ahead of the game. You've gained. But if you get it wrong, you've only added complexity that makes it more difficult to change your software. You're obviously not getting the payback.


What does this mean? This means we should stop making such an attempt to create the most flexible, catch-all algorithms and frameworks possible, and instead begin focusing on the problem domain. Instead of trying to discover the wheel, start addressing the problem you're paid to solve, and do it simply, directly and without unneeded abstractions (see: YAGNI). This is what it means to "code light". Keep the weight of your architecture and your algorithms light. Don't over abstract. KISS.

Now, don't get me wrong... I love the new stuff as much as the next guy, but the new stuff has it's place. Our primary goal when learning a new framework or a new technology is not to look for places to use it, but to instead figure out where it should be used, while continuing to default to the simplest solution possible. Sometimes the simplest solution is the new language or framework, and sometimes it's not. It's the role of the adventurous geek to learn how to discern the difference.

That being said, welcome to the "re-branded" blog. I have no plans to stop blogging on some of the algorithms and tricks I've discovered or seen other people use, but I do have plans to start increasing posts about coding standards, simplicity, and other language-agnostic thoughts.

Glad you could drop by.

EDIT: Based on a comment by Ben Scheirman, I've decided, despite my love for the label cloud, to remove it completely, as an action to be taken to demonstrate my new commitment to simplicity, not only in coding, but in the design of the site itself. Turns out nobody really used it anyways, so it was just cluttering things up.

Wednesday, July 29, 2009

Assembly Resolution with AppDomain.AssemblyResolve

Plugin frameworks often rely on runtime assembly resolution, and sometimes the assemblies to be resolved don't lie within the directory structure of the executable, nor are they located in the GAC. In these cases, you can use the AppDomain.AssemblyResolve event to resolve assemblies at runtime. The key with the AssemblyResolve method is that it must be put into place before attempting to instantiate any of the classes where an assembly needs to be loaded. Sample code exists on the MSDN Documentation for System.Assembly.AssemblyResolve.

Before implementing runtime assembly resolution, it's important to understand how methods are loaded at runtime.

When a method is first called, that method is JITted, or "Just-In-Time Compiled". Essentially, all the IL code for that method is loaded and then compiled into CPU instructions. Any types that are used within that method are also resolved when the method is JIT compiled, in order to ensure that the entire method is "safe" for execution. Essentially, what this means to Assembly Resolution using the AppDomain.AssemblyResolve event is that the attachment to the event handler cannot reside within the same method that calls the type that will have to be resolved using the event handler. The reason for this is simple... the event handler must be attached before the type is resolved. If the event handler is attached within the same method, then the JIT compiler will attempt to resolve the type before executing the first instruction in the method, including the instruction to attach the event handler to the AssemblyResolve event, causing the whole application to fail.

Thus, a good example of attaching an assembly at runtime would be the following. The Widget class is the class to load, and it does not reside within the same directory as the executable. Instead, it resides in a directory that is only identified with a relative path. This relative path can be searched at runtime to find the specific assembly that is needed to load.


using System;
using System.IO;
using System.Reflection;
using ClassLibrary1;

namespace ConsoleApplication6
{
internal class Program
{
private const string ResolutionPath = @"..\..\..\ClassLibrary1\bin\debug\";

private static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainAssemblyResolve;
RunWidget();
}

private static void RunWidget()
{
var widget = new WidgetInOtherAssembly();
Console.WriteLine(widget);
}

private static Assembly CurrentDomainAssemblyResolve(object sender, ResolveEventArgs args)
{
Assembly[] currentAssemblies = AppDomain.CurrentDomain.GetAssemblies();

for (int i = 0; i < currentAssemblies.Length; i++)
{
if (currentAssembliesi.FullName == args.Name)
{
return currentAssembliesi;
}
}

return FindAssembliesInDirectory(args.Name, ResolutionPath);
}

private static Assembly FindAssembliesInDirectory(string assemblyName, string directory)
{
foreach (string file in Directory.GetFiles(directory))
{
Assembly assm;

if (TryLoadAssemblyFromFile(file, assemblyName, out assm))
return assm;
}

return null;
}

private static bool TryLoadAssemblyFromFile(string file, string assemblyName, out Assembly assm)
{
try
{
// Convert the filename into an absolute file name for
// use with LoadFile.
file = new FileInfo(file).FullName;

if (AssemblyName.GetAssemblyName(file).FullName == assemblyName)
{
assm = Assembly.LoadFile(file);
return true;
}
}
catch
{
/* Do Nothing */
}
assm = null;
return false;
}
}
}


Changes To ResolveEventArgs in .NET 4.0

In .NET 4.0, the ResolveEventArgs class has a new property called "RequestingAssembly", which returns the name of the assembly requesting resolution. This has been done in order to enable the ability to execute specific code based on which assembly was requesting the resolution.

You can see more information on these changes here.

Tuesday, July 28, 2009

On Method Overloading Best Practices

C# allows method overloading. An overload is defined as a method that has the same name as another method, and differs only in the number and/or type of parameters it receives. (Technically, .NET allows creation of overloads based only on the return type but this construct is not allowed in C#).

The .NET Framework uses method overloading with several of it's methods. For example, the Activator.CreateInstance method has no fewer than 14 distinct overloads for it's usage. Each of these overloads provides the developer flexibility with how he/she chooses to call this method, and can greatly abstract out some of the more menial tasks that may have to be done by the developer, such as casting from one type to another before making a call, or having to research default parameters for a method in order to ensure the proper parameters are passed into the method.

When to Use Method Overloading

Method overloading should be used to allow your callers greater type and parameter options when calling a specific method. Good uses of method overloading are as follows:

Default values

When a method has parameters for which "acceptable defaults" can be defined, an overload of that method that omits the defaulted parameter can be created which would subsequently call the method that contains the parameter for which there is a default, passing in the default value. An example of this might be the Int32.TryParse method, which has two overloads:


bool TryParse(string s, out int result);
bool TryParse(string s, NumberStyles style, IFormatProvider provider, out int result);


Both of these methods ultimately route to the same method, namely the internal static method Number.TryParseInt32. The difference is that the first one passes NumberStyles.Integer and NumberFormatInfo.CurrentInfo as the default values for style and provider, whereas the second overload passes the user defined values. Therefore, the first one is provided for convenience for default values.

Type conversion convenience

If a piece of data can be represented using multiple types, then overloads can be created to abstract type conversions away from the client. An example might be a fictional "CreateInstance" method.


T CreateInstance();
object CreateInstance(Type type);
object CreateInstance(string typeName);


These three methods all accomplish the same purpose, namely, creating an instance from a representation of a type. Two of them are overloads. In the first method, the representation is passed via a generic type parameter, T. The next method passes the type via an instance of the Type class, and the third method (which is an overload of the second method) passes the type via it's full name. It's important to note that these three parameter types are intrinsically the same piece of data only represented in different ways. They all three represent a single type, which is then used to create an instance. If I wanted to then create an instance of a class based on another piece of data other than the type, I should not create an overload, but should create a new method with a new method name.

When Not to Use Overloading

There are a couple of instances where method overloads would not be appropriate.

To clean up Intellisense

Designing anything within an object model simply to cater to ease of use when it comes to a specific technology is almost always a mistake. Cleaning up Intellisense is not related to having a clear code base, and catering to Intellisense in this situation can muddle the true purpose of your methods.

To take advantage of the type differences of intrinsically different pieces of data

An example of this could be overloads like the following:


Product GetProduct(Guid id);
Product GetProduct(string name);


The first issue here would be that the name of the methods, GetProduct, does not accurately or completely describe the actions that the method would take in order to accomplish it's goal. In both situations, a Product instance is retrieved, but both situations accomplish this task based on intrinsically different data. An id is not a name, and cannot be converted to a name without having more information. Creating this kind of overload makes compiler resolutions dependent upon whatever type the data happens to be at the moment.

Also, potential inconsistencies in naming can occur in the situation where a third overload is to be added. Suppose there is a client reference number for each product, and a third overload needs to be created to manage fetching products by this number. Suppose, furthermore, that the client reference number is of the type string. The preferred overload would look like this:


Product GetProduct(string clientRef);


Unfortunately, since overloads are only distinguished based on the name and the incoming parameter types, the above method would cause a compiler error when combined with the previous two methods, leaving the developer with only two choices: rename all the methods for consistency, which would also force callers to change their code, or else use a different name for the new method, causing an inconsistency, and learn to deal with it. Of course, either option is no good.

In the end, the best option is to only use method overloading when the methods to be overloaded accomplish the exact same task given the same data where portions of the data either have acceptable default values, or else are already the same bit of data only represented in different formats.

Monday, July 27, 2009

Automatically Find the Namespace of a Class and Add a Using Statement in Visual Studio

This is an all-too-common question on the forums for me not to address it here. This post concerns a very basic C# concept.

Sometimes, when adding a code snippet, it's possible you might get an error that says something to the effect of "The name "xxx" does not exist in the current context".

At compile time, a namespace reference must be found in order to resolve classes that will be used within an application. Classes can be resolved to their namespaces either with the using directive, or by using the fully qualified class name when referring to a class.

Employing the using directive would look like this:


using System;
using System.Reflection;

namespace MyNamespace
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine(Assembly.GetExecutingAssembly().GetName().Version);
}
}
}


While employing a fully qualified namespace reference would look like this:


namespace MyNamespace
{
public class Program
{
public static void Main(string[] args)
{
System.Console.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);
}
}
}


Typically, the using directive is preferred, as it usually creates cleaner, and easier to read code, but sometimes the fully qualified class name makes more sense, especially when two or more namespaces contain different classes with the same name.

If both of these above constructs are missing from the code file, the error described above will be the result.

Most of the time, this situation can be done by following the following simple steps:

1. Place the text caret in the middle of the class name that is causing the error. Alternatively, you can simply double click on the error in the Errors window.

2. Press Shift+Alt+F10. If the class can be found, a set of options will appear to add the namespace reference to the class. The options that start with "using" will add the using directive to the top of the code file, while the options that simply have the namespace name will change the class reference in code to use the fully qualified class name.

Occasionally, however, it's necessary to add a reference to the assembly containing the class. You can do this by right clicking the "References" folder within the project, and selecting "Add Reference....". Select the applicable tab:

.NET - For .NET Assemblies located in the GAC.

COM - For older COM assemblies registered in the system.

Projects - For references to projects that reside within the same solution as the current project.

Browse - To browse the file system for a specific file.

Recent - For references that have recently been added.

Finally, select the assembly you need to reference, and click OK.

After a reference has been added, you can go back to step 1 above, and ensure the using directive or the fully qualified class name results in the proper resolution of the class.

Wednesday, July 15, 2009

IOException While Trying to Delete a Folder?!

Make sure you don't step on your own toes. The following code illustrates...


using System;
using System.IO;

internal class Program
{
private static void Main(string[] args)
{
string directory = @"C:\atemporaryfolder\";
Directory.CreateDirectory(directory);
Environment.CurrentDirectory = directory;
Directory.Delete(directory);
}
}


Who's using the folder? You are. Whenever Environment.CurrentDirectory is set in an application, it prevents anything else from deleting the folder. Note that the Environment.CurrentDirectory can also be set through a variety of other means, including the FolderBrowserDialog, OpenFileDialog and SaveFileDialog.

What's the solution? Simple. Set Environment.CurrentDirectory to something else. @"C:\" works just fine.

Tuesday, July 14, 2009

C# 3.0 Syntax of the Day

Can't believe I missed this one...


var items = new string[] { "David", "Jennifer" };


versus:


var items = new[] { "David", "Jennifer" };


Yep, that's right! "new[]" is okay. The compiler will infer the type of the array based on the type of the items within the squigglies.

Monday, July 13, 2009

Truncation and Rounding in Conversion

Just found this. Feels angry:


decimal d = 1.7M;
Console.WriteLine((long)d);
Console.WriteLine(Convert.ToInt64(d));


Yields:

1
2

Ouch.

Remember, kids, casting syntax truncates, while using the Convert class rounds.

Friday, July 10, 2009

A WebBrowser Implementation That Actually Raises Events!

A question that comes up rather frequently on the Forums is "Why doesn't the WebBrowser event ___________ ever get raised?" Typically, the blank is filled in with "MouseClick" and "KeyDown" and other input events. The reason for this is the fact that the WebBrowser control is an ActiveX-based control. Essentially, all of the events that would normally be raised by the control itself, are instead captured inside the document that resides within the control. In order to get the events to be raised at the control level, it's important to attach the event handlers to the document, and not the control. Unfortunately, the default implementation of WebBrowser doesn't expose the document's events at this level, so you're left with no way of tracking what's happening within the WebBrowser control, as far as input is concerned. Well, no more. Here's an implementation of WebBrowser, called ActiveWebBrowser, that can handle these events, and exposes them publicly at the WebBrowser level, without interfering with the existing events on the page.

This code will require you to reference the COM library called "Microsoft HTML Object Library" in your code, which should be available through the COM tab in the Add References dialog.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices.ComTypes;
using mshtml;


namespace WindowsFormsApplication1
{
public class MSHtmlEventArgs : EventArgs
{
public MSHtmlEventArgs(mshtml.IHTMLEventObj obj)
{
EventObj = obj;
}

public mshtml.IHTMLEventObj EventObj { get; private set; }
}


public class ActiveWebBrowser : WebBrowser
{
private IConnectionPoint icp;
private int cookie = -1;

public event EventHandler<MSHtmlEventArgs> DocumentActivate;
public event EventHandler<MSHtmlEventArgs> DocumentAfterUpdate;
public event EventHandler<MSHtmlEventArgs> DocumentBeforeActivate;
public event EventHandler<MSHtmlEventArgs> DocumentBeforeDeactivate;
public event EventHandler<MSHtmlEventArgs> DocumentBeforeEditFocus;
public event EventHandler<MSHtmlEventArgs> DocumentBeforeUpdate;
public event EventHandler<MSHtmlEventArgs> DocumentCellChange;
public event EventHandler<MSHtmlEventArgs> DocumentClick;
public event EventHandler<MSHtmlEventArgs> DocumentContextMenu;
public event EventHandler<MSHtmlEventArgs> DocumentControlSelect;
public event EventHandler<MSHtmlEventArgs> DocumentDataAvailable;
public event EventHandler<MSHtmlEventArgs> DocumentDataSetChanged;
public event EventHandler<MSHtmlEventArgs> DocumentDataSetComplete;
public event EventHandler<MSHtmlEventArgs> DocumentDoubleClick;
public event EventHandler<MSHtmlEventArgs> DocumentDeactivate;
public event EventHandler<MSHtmlEventArgs> DocumentDragStart;
public event EventHandler<MSHtmlEventArgs> DocumentErrorUpdate;
public event EventHandler<MSHtmlEventArgs> DocumentFocusIn;
public event EventHandler<MSHtmlEventArgs> DocumentFocusOut;
public event EventHandler<MSHtmlEventArgs> DocumentHelp;
public event EventHandler<MSHtmlEventArgs> DocumentKeyDown;
public event EventHandler<MSHtmlEventArgs> DocumentKeyPress;
public event EventHandler<MSHtmlEventArgs> DocumentKeyUp;
public event EventHandler<MSHtmlEventArgs> DocumentMouseDown;
public event EventHandler<MSHtmlEventArgs> DocumentMouseMove;
public event EventHandler<MSHtmlEventArgs> DocumentMouseUp;
public event EventHandler<MSHtmlEventArgs> DocumentMouseOut;
public event EventHandler<MSHtmlEventArgs> DocumentMouseOver;
public event EventHandler<MSHtmlEventArgs> DocumentMouseWheel;
public event EventHandler<MSHtmlEventArgs> DocumentPropertyChange;
public event EventHandler<MSHtmlEventArgs> DocumentReadyStateChange;
public event EventHandler<MSHtmlEventArgs> DocumentRowEnter;
public event EventHandler<MSHtmlEventArgs> DocumentRowExit;
public event EventHandler<MSHtmlEventArgs> DocumentRowsDelete;
public event EventHandler<MSHtmlEventArgs> DocumentRowsInserted;
public event EventHandler<MSHtmlEventArgs> DocumentSelectionChange;
public event EventHandler<MSHtmlEventArgs> DocumentSelectStart;
public event EventHandler<MSHtmlEventArgs> DocumentStop;

protected override void OnDocumentCompleted(WebBrowserDocumentCompletedEventArgs e)
{
base.OnDocumentCompleted(e);

IConnectionPointContainer icpc;
icpc = (IConnectionPointContainer)this.Document.DomDocument;
Guid guid = typeof(HTMLDocumentEvents2).GUID;
icpc.FindConnectionPoint(ref guid, out icp);
icp.Advise(new HandleWebBrowserDHTMLEvents(this), out cookie);
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (-1 != cookie) icp.Unadvise(cookie);
cookie = -1;
}
base.Dispose(disposing);
}

class HandleWebBrowserDHTMLEvents : mshtml.HTMLDocumentEvents2
{
private ActiveWebBrowser _webBrowser;

public HandleWebBrowserDHTMLEvents(ActiveWebBrowser webBrowser)
{
_webBrowser = webBrowser;
}

public void onactivate(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentActivate != null)
_webBrowser.DocumentActivate(_webBrowser, new MSHtmlEventArgs(e));
}

public void onafterupdate(mshtml.IHTMLEventObj e) {
if (_webBrowser.DocumentAfterUpdate != null)
_webBrowser.DocumentAfterUpdate(_webBrowser, new MSHtmlEventArgs(e));
}

public bool onbeforeactivate(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentBeforeActivate != null)
_webBrowser.DocumentBeforeActivate(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public bool onbeforedeactivate(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentBeforeDeactivate != null)
_webBrowser.DocumentBeforeDeactivate(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public void onbeforeeditfocus(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentBeforeEditFocus != null)
_webBrowser.DocumentBeforeEditFocus(_webBrowser, new MSHtmlEventArgs(e));
}

public bool onbeforeupdate(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentBeforeUpdate != null)
_webBrowser.DocumentBeforeUpdate(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public void oncellchange(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentCellChange != null)
_webBrowser.DocumentCellChange(_webBrowser, new MSHtmlEventArgs(e));
}

public bool onclick(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentClick != null)
_webBrowser.DocumentClick(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public bool oncontextmenu(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentContextMenu != null)
_webBrowser.DocumentContextMenu(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public bool oncontrolselect(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentControlSelect != null)
_webBrowser.DocumentControlSelect(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public void ondataavailable(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentDataAvailable != null)
_webBrowser.DocumentDataAvailable(_webBrowser, new MSHtmlEventArgs(e));
}

public void ondatasetchanged(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentDataSetChanged != null)
_webBrowser.DocumentDataSetChanged(_webBrowser, new MSHtmlEventArgs(e));
}

public void ondatasetcomplete(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentDataSetComplete != null)
_webBrowser.DocumentDataSetComplete(_webBrowser, new MSHtmlEventArgs(e));
}

public bool ondblclick(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentDoubleClick != null)
_webBrowser.DocumentDoubleClick(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public void ondeactivate(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentDeactivate != null)
_webBrowser.DocumentDeactivate(_webBrowser, new MSHtmlEventArgs(e));
}

public bool ondragstart(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentDragStart != null)
_webBrowser.DocumentDragStart(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public bool onerrorupdate(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentErrorUpdate != null)
_webBrowser.DocumentErrorUpdate(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public void onfocusin(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentFocusIn != null)
_webBrowser.DocumentFocusIn(_webBrowser, new MSHtmlEventArgs(e));
}

public void onfocusout(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentFocusOut != null)
_webBrowser.DocumentFocusOut(_webBrowser, new MSHtmlEventArgs(e));
}

public bool onhelp(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentHelp != null)
_webBrowser.DocumentHelp(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public void onkeydown(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentKeyDown != null)
_webBrowser.DocumentKeyDown(_webBrowser, new MSHtmlEventArgs(e));
}

public bool onkeypress(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentKeyPress != null)
_webBrowser.DocumentKeyPress(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public void onkeyup(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentKeyUp != null)
_webBrowser.DocumentKeyUp(_webBrowser, new MSHtmlEventArgs(e));
}

public void onmousedown(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentMouseDown != null)
_webBrowser.DocumentMouseDown(_webBrowser, new MSHtmlEventArgs(e));
}

public void onmousemove(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentMouseMove != null)
_webBrowser.DocumentMouseMove(_webBrowser, new MSHtmlEventArgs(e));
}

public void onmouseout(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentMouseOut != null)
_webBrowser.DocumentMouseOut(_webBrowser, new MSHtmlEventArgs(e));
}

public void onmouseover(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentMouseOver != null)
_webBrowser.DocumentMouseOver(_webBrowser, new MSHtmlEventArgs(e));
}

public void onmouseup(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentMouseUp != null)
_webBrowser.DocumentMouseUp(_webBrowser, new MSHtmlEventArgs(e));
}

public bool onmousewheel(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentMouseWheel != null)
_webBrowser.DocumentMouseWheel(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public void onpropertychange(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentPropertyChange != null)
_webBrowser.DocumentPropertyChange(_webBrowser, new MSHtmlEventArgs(e));
}

public void onreadystatechange(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentReadyStateChange != null)
_webBrowser.DocumentReadyStateChange(_webBrowser, new MSHtmlEventArgs(e));
}

public void onrowenter(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentRowEnter != null)
_webBrowser.DocumentRowEnter(_webBrowser, new MSHtmlEventArgs(e));
}

public bool onrowexit(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentRowExit != null)
_webBrowser.DocumentRowExit(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public void onrowsdelete(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentRowsDelete != null)
_webBrowser.DocumentRowsDelete(_webBrowser, new MSHtmlEventArgs(e));
}

public void onrowsinserted(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentRowsInserted != null)
_webBrowser.DocumentRowsInserted(_webBrowser, new MSHtmlEventArgs(e));
}

public void onselectionchange(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentSelectionChange != null)
_webBrowser.DocumentSelectionChange(_webBrowser, new MSHtmlEventArgs(e));
}

public bool onselectstart(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentSelectStart != null)
_webBrowser.DocumentSelectStart(_webBrowser, new MSHtmlEventArgs(e));
return true;
}

public bool onstop(mshtml.IHTMLEventObj e)
{
if (_webBrowser.DocumentStop != null)
_webBrowser.DocumentStop(_webBrowser, new MSHtmlEventArgs(e));
return true;
}
}
}
}

Wednesday, July 1, 2009

I'm an MVP!

So, I received an email from Microsoft this morning. Apparently I've been awarded Microsoft's Most Valuable Professional (MVP) Award in Visual C#! Thanks Microsoft!

I plan to just "keep on keepin' on" and continue helping people on the MSDN Forums as best as I know how, and to continue providing the best content I know how to give here on my blog.

Wednesday, June 24, 2009

How to Load an XmlDocument and Completely Ignore DTD

A question came up on the Forums today from someone looking to ignore the DOCTYPE tag on an XML file while loading an XML file into an XmlDocument class instance without first reading the whole file and using something like Regex to replace the element. In other words, he was looking for a fast performing solution.

The XmlDocument class loads XML files via the Load or LoadXml methods, which all ultimately convert to an XmlTextReader before reading the XML. There's one exception to this rule, however, and that's the Load overload that accepts an XmlReader.

More than this, it's the XmlReader, and not the XmlDocument that resolves DTD validation arguments. It does this by using the XmlResolver set in the XmlReaderSettings.XmlResolver property.

To solve this issue, create an instance of XmlReaderSettings, and allow DTD processing by setting ProhibitDTD to false, but then remove the ability for the XmlReader to resolve the address specified in the DOCTYPE element by setting the XmlResolver property to null. After doing this, you can safely create an XmlReader, and pass the reader into the Load method of the XmlDocument, and the XmlDocument will load the specified XML file without validating the document.

The following code assumes you have your XML file loaded into a Stream named "xmlStream".


// Create an XmlReaderSettings object.  
XmlReaderSettings settings = new XmlReaderSettings();

// Set XmlResolver to null, and ProhibitDtd to false.
settings.XmlResolver = null;
settings.ProhibitDtd = false;

// Now, create an XmlReader. This is a forward-only text-reader based
// reader of Xml. Passing in the settings will ensure that validation
// is not performed.
XmlReader reader = XmlTextReader.Create(xmlStream, settings);

// Create your document, and load the reader.
XmlDocument doc = new XmlDocument();
doc.Load(reader);