2008-08-21

Error creating window handle.

I have been chasing a bug in a VB.NET Windows Forms application today. The error log was filled with Win32Exception Error creating window handle. Digging in the usage log I loacted the following code.

   1: Public Sub DataBindRadioButton(ByVal radioButton As Windows.Forms.RadioButton, ByVal radioButtonTrueValue As Object, ByVal radioButtonFalseValue As Object, ByRef dataSource As Object, ByVal dataMember As String)
   2:      Dim propertyHolder As New propertyHolder(radioButton, radioButtonTrueValue, radioButtonFalseValue, dataSource, dataMember)
   3:      propertyHolder.Name = radioButton.Name & "propertyHolder"
   4:  
   5:      For Each control As control In radioButton.FindForm.Controls
   6:          If control.Name = propertyHolder.Name Then
   7:              radioButton.FindForm.Controls.Remove(control)
   8:              Exit For
   9:          End If
  10:      Next
  11:  
  12:      radioButton.FindForm.Controls.Add(propertyHolder)
  13:  End Sub

propertyHolder is a Control.

So whats the memory leak here?

radioButton.FindForm.Controls.Remove(control), since we remove the control from the container(Form). We now inherit the responsibility to clean up.

So a non leaking version would be.

   1: Public Sub DataBindRadioButton(ByVal radioButton As Windows.Forms.RadioButton, ByVal radioButtonTrueValue As Object, ByVal radioButtonFalseValue As Object, ByRef dataSource As Object, ByVal dataMember As String)
   2:       Dim propertyHolder As New propertyHolder(radioButton, radioButtonTrueValue, radioButtonFalseValue, dataSource, dataMember)
   3:       propertyHolder.Name = radioButton.Name & "propertyHolder"
   4:  
   5:       For Each control As control In radioButton.FindForm.Controls
   6:           If control.Name = propertyHolder.Name Then
   7:               radioButton.FindForm.Controls.Remove(control)
   8:       control.Dispose()
   9:               Exit For
  10:           End If
  11:       Next
  12:  
  13:       radioButton.FindForm.Controls.Add(propertyHolder)
  14:   End Sub

So remember to dispose a control when you dynamically remove it from its container.

The application also had a while loop that in some conditions never exited, and called the above method.

Delegates - Late Bound VS Expression

With the new Expressions .NET 3.5, is there any reason to use a late bound delegate?
Lets put it to the test.

lateboundvsexpression

Milliseconds/number of iterations.  (less is better.)

Expressions have almost constant time, while LateBound suffers under many iterations.

And the test code.

   1: using System;
   2: using System.Diagnostics;
   3: using System.Linq.Expressions;
   4: using System.Reflection;
   5: using NUnit.Framework;
   6:  
   7: namespace Sample
   8: {
   9:     [TestFixture]
  10:     public class LateBoundVSExpressionCall
  11:     {
  12:         [Test]
  13:         public void TestLateBound()
  14:         {
  15:             object instance = new object();
  16:             Stopwatch stopwatch = Stopwatch.StartNew();
  17:             MethodInfo methodInfo = typeof(object).GetMethod("ToString");
  18:             for (int i = 0; i < 1000000; i++)
  19:             {
  20:                 methodInfo.Invoke(instance, null);
  21:             }
  22:             stopwatch.Stop();
  23:             Trace.WriteLine("LateBound: " + stopwatch.ElapsedMilliseconds + " milliseconds");
  24:         }
  25:  
  26:         [Test]
  27:         public void TestExpression()
  28:         {
  29:             object instance = new object();
  30:             Stopwatch stopwatch = Stopwatch.StartNew();
  31:             MethodInfo methodInfo = typeof(object).GetMethod("ToString");
  32:             ConstantExpression constantExpression = Expression.Constant(instance);
  33:             MethodCallExpression methodCallExpression = Expression.Call(constantExpression, methodInfo);
  34:             Func toString = Expression.Lambda>(methodCallExpression).Compile();
  35:             for (int i = 0; i < 1000000; i++)
  36:             {
  37:                 toString();
  38:             }
  39:             stopwatch.Stop();
  40:             Trace.WriteLine("ExpressionCall: " + stopwatch.ElapsedMilliseconds + " milliseconds");
  41:         }
  42:     }
  43: }

So with just a few extra calls to Expression, we get run time il, that performs a lot better.

2008-08-13

Onion Architecture in Praxis

What is it?

Jeffrey Palermo has coined the pattern onion architecture, so what is it?

Actually it is "just" my default architecture, and has been for some time now. The ideas behind are not new, and it is related to other principles and patterns. Never the less I really like having a name for it, so we have a common understanding of it.

How I use Assemblies and Namespaces

First of I am a bit of a namespace fascist, every namespace in an assembly starts with the root name(The root name is the assembly name part before the first ".").

Assembly: MyDomainCore.dll

Namespaces would be something like: MyDomainCore, MyDomainCore.Something, MyDomainCore.SomethingElse etc.

Also I use folders for namespaces, so that files are located in a folder path that matches the namespace path.

How I use Namespace References

Any namespace can reference another namespace as long as it has another root name.

MyDomainTesting -> MyDomainCore (OK)

Any namespace can reference another namespace with the same root name, as long as the namespace is closer to the root name.

MyDomainCore.Infrastructure -> MyDomainCore (OK)

MyDomainCore -> MyDomainCore.Infrastructure (Not OK)

Visual Studio Solutions, Projects, and folder structure

MyDomain (Solution)

MyDomainCore (Project)

    Infrastructure (Folder)

        Bootstrapping (Folder)

MyDomainApplication (Project) [Reference to MyDomainCore]

MyDomainTesting (Project) [Reference to MyDomainCore and MyDomainApplication]

 

This is the initial setup, from here it can grow to more complex scenarios, like multiple Infrastructure implementations  or multiple applications (web, rich client, web service etc.).

What goes where?

MyDomainCore should only be POCO classes as a model and should not contain references to System.IO, NHibernate, Web or anything other that is remotely infrastructure related. It provides abstractions (abstract classes or interfaces) for Business Services used by the core(think SendEmailService and Repository). Applications Services group together the model for a given user scenario.

MyDomainCore.Infrastructure implements the business services of MyDomainCore. SendEmailService could be implemented as an SmtpSendEmailService. Repository could be implemented as a NHibernateRepository etc. Most Services will also have a stub implementation, like StubRepository and StubSendEmailService.
Classes in MyDomainCore.Infrastructure should in general not use any classes from this namespace, and should be as light as possible in.

MyDomainCore.Infrastructure.Bootstrapping wires the MyDomainCore and MyDomainCore.Infrastructure together, usually with an IOC Container. It can be configured for stub or normal usage.
It is placed in it own namespace so that I cant be referenced from the same name root.

MyDomainApplication when it is a GUI, it parses the raw user input and relays the request to the Application Services, for validation and processing. Its main purpose is to render the UI and to receive user input.

MyDomainTesting contains all automated tests, unit, integration - or as I usually categorize them Fast and Slow.

2008-08-11

How to configure NHibernateFacility in code

I haven't started using Burrow yet, so I still depend on the NHibernateFacility in the castle stack. But I really don't like to pay my angle bracket tax, so I want to configure it in code.

   1: private void CreateItem(MutableConfiguration parent, string key, string value)
   2: {
   3:   MutableConfiguration item = parent.CreateChild("item");
   4:   item.Attributes.Add("key", key);
   5:   item.Value = value;
   6: }
   7:  
   8: public void Init()
   9: {
  10:   MutableConfiguration facility = new MutableConfiguration("facility");
  11:   facility.Attributes.Add("id", "nhibernatefacility");
  12:   facility.Attributes.Add("isWeb", "isWeb");
  13:   facility.Attributes.Add("defaultFlushMode", "Commit");
  14:   facility.Attributes.Add("type", "Castle.Facilities.NHibernateIntegration.NHibernateFacility, Castle.Facilities.NHibernateIntegration");
  15:   MutableConfiguration factory = facility.CreateChild("factory");
  16:   factory.Attributes.Add("id", "nhibernate.factory");
  17:   MutableConfiguration settings = factory.CreateChild("settings");
  18:  
  19:   CreateItem(settings, "connection.provider", "NHibernate.Connection.DriverConnectionProvider");
  20:   CreateItem(settings, "connection.driver_class", "NHibernate.Driver.SqlClientDriver");
  21:   CreateItem(settings, "connection.connection_string", "Data Source=SERVER;Initial Catalog=DATABASE;Integrated Security=SSPI");
  22:   CreateItem(settings, "dialect", "NHibernate.Dialect.MsSql2005Dialect");
  23:   CreateItem(settings, "show_sql", "true");
  24:  
  25:   MutableConfiguration assemblies = factory.CreateChild("assemblies");
  26:   MutableConfiguration assembly = assemblies.CreateChild("assembly");
  27:   assembly.Value = "HomeForretningCore";
  28:  
  29:   IWindsorContainer container = new WindsorContainer(); 
  30:   container.Kernel.ConfigurationStore.AddFacilityConfiguration("nHibernateFacility", facility);
  31:   container.AddFacility("nHibernateFacility");
  32: }