Tuesday, September 28, 2010

WCF, CSLA, Binary Serialisation and XmlException

We've been having some issues with using CSLA and the WCF DataPortal where we are seeing a stack of System.Xml.XmlExceptions appearing in the output window with no immediately discernible cause. Turning on "Break on unhandled exceptions" yielded the following exception message:

The '<' character, hexadecimal value 0x3C, cannot be included in a name.

We're using binary serialisation, and it turns out that the backing fields created for automatic properties are to blame - they wrap the type name in angle brackets and append a unique suffix.

The only apparent solution to this is to not use automatic properties - binary serialisation works with fields, not properties, and we have no control of the naming convention used for backing fields of automatic properties. Using the [field:NonSerialized] attribute also did not work, unfortunately.

I'm not 100% sure why this results in an XmlException, since we're using binary serialisation, but I'm assuming WCF will wrap all responses in an XML packet regardless. I'm also not sure if this is something that is specific to CSLA or just WCF in general, but if you're seeing this exception in your output window, automatic properties are to blame.

Labels: , ,

Thursday, September 16, 2010

WPF ComboBox Retardation

A colleague found an "interesting" issue with ordering of XAML attributes on ComboBoxes in WPF the other day. His email says it well:

Dear nerds,

We can all tell tales about how tarded WPF is, but this one comes right at the top of my list. In markup languages the sequence of attributes in a tag don't have any significance, but in XAML which is happy child of the markup family this seems to have a significance that is never mentioned. This should not concern independent attributes but the ones that do depend on each other may not work properly if specified the wrong way around. An example which I battled with today is when specifiying the binding for source and selected value in a combo box. The correct order is:

Wrong:

<ComboBox Grid.Row="2" Grid.Column="2" Style="{StaticResource ComboBoxStyle}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="MAPSSubCategoryValue" SelectedValuePath="MAPSSubCategoryId" ItemsSource="{Binding Path=SubCategories, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" SelectedItem="{Binding Path=SelectedMAPSSubCategory, Mode=OneWayToSource, ValidatesOnDataErrors=True}" />

Correct :

<ComboBox Grid.Row="2" Grid.Column="2" Style="{StaticResource ComboBoxStyle}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="MAPSSubCategoryValue" SelectedValuePath="MAPSSubCategoryId" SelectedItem="{Binding Path=SelectedMAPSSubCategory, Mode=OneWayToSource, ValidatesOnDataErrors=True}" ItemsSource="{Binding Path=SubCategories, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" />

ItemsSource should be placed after SelectedItem. The reason behind it is quite unreasonable (which defies the purpose of a reason) but seems to be caused by the fact that these two properties are essentially bound to the same dependency property. In fact SelectedItem is bound to a subset of ItemsSource, so when WPF goes and re-sets these in the order specified :), if items source is first, it invalidates the selection for SelectedItem, but that does not happen the other way around.

This should not matter for other cases in which the dependency properties are independent, but you'd be surprised.

Cheers, Shuku

Labels: ,

Thursday, September 02, 2010

Automatically Register Implementers of a Generic Interface With Unity

It's quite a common pattern to have a generic interface that is implemented by a number of concrete types and to want to be able to instantiate the concrete implementation by the type of generic parameter.

For example, given an interface IPat<T>, concrete classes Cat and Dog, we might have CatPatter implementing IPat<Cat> and DogPatter implementing IPat<Dog>. With no IoC container, to pat our pet based on the type of pet, our code needs the explicit knowledge that the CatPatter and DogPatter classes implement IPat<T>.

With an IoC container, we can register the types so all we need to do is ask the container for an instance of IPat<T> for out type of pet, but (at least with Unity) we still need to manually register each implementation of the IPat<> interface. This is clearly not ideal!

With a bit of reflection funkery, we can automatically register types that implement a generic interface.

    1       public static void RegisterAllTypesForOpenGeneric(this IUnityContainer container, Type openGenericType, Assembly targetAssembly)

    2       {

    3          if (!openGenericType.IsGenericTypeDefinition)

    4             throw new ArgumentException("typeToRegister must be an open generic type", "typeToRegister");

    5 

    6          foreach (Type type in targetAssembly.GetExportedTypes())

    7          {

    8             if (openGenericType.IsInterface)

    9                RegisterInterfaceTypes(container, openGenericType, type, type);

   10             else

   11                RegisterBaseTypes(container, openGenericType, type, type);           

   12          }

   13       }

   14 

   15       private static void RegisterInterfaceTypes(IUnityContainer container, Type openGenericType, Type targetType, Type typeToRegister)

   16       {

   17          foreach (Type interfaceType in targetType.GetInterfaces())

   18             if (interfaceType.IsGenericType && !interfaceType.ContainsGenericParameters && openGenericType.IsAssignableFrom(interfaceType.GetGenericTypeDefinition()))

   19                container.RegisterType(interfaceType, typeToRegister);

   20       }

   21 

   22       private static void RegisterBaseTypes(IUnityContainer container, Type openGenericType, Type targetType, Type typeToRegister)

   23       {

   24          if (targetType.BaseType != null && targetType.BaseType != typeof(object))

   25             if (targetType.BaseType.IsGenericType && openGenericType.IsAssignableFrom(targetType.BaseType.GetGenericTypeDefinition()))

   26                container.RegisterType(targetType.BaseType, typeToRegister);

   27             else

   28                RegisterBaseTypes(container, openGenericType, targetType.BaseType, typeToRegister);

   29       }

and some unit tests to make sure all is playing the game:

    1    [TestClass]

    2    public class AutoRegistrationTest

    3    {

    4       [TestMethod]

    5       public void WhenPassedOpenGenericInterfaceType_AllDerivedTypesAreRegistered()

    6       {

    7          // use a strict mock to ensure no other types are registered

    8          var container = MockRepository.GenerateStrictMock<UnityContainerBase>();

    9          container.Expect(x => x.RegisterType(typeof(ITest<A>), typeof(TestA))).Return(container);

   10          container.Expect(x => x.RegisterType(typeof(ITest<B>), typeof(TestB))).Return(container);

   11          container.RegisterAllTypesForOpenGeneric(typeof(ITest<>));

   12       }

   13 

   14       [TestMethod]

   15       public void WhenPassedOpenGenericConcreteType_AllDerivedTypesAreRegistered()

   16       {

   17          // use a strict mock to ensure no other types are registered

   18          var container = MockRepository.GenerateStrictMock<UnityContainerBase>();

   19          container.Expect(x => x.RegisterType(typeof(TestBase<A>), typeof(TestA))).Return(container);

   20          container.Expect(x => x.RegisterType(typeof(TestBase<B>), typeof(TestB))).Return(container);

   21          container.RegisterAllTypesForOpenGeneric(typeof(TestBase<>));

   22       }

   23 

   24       [TestMethod]

   25       public void WhenBaseClassImplementsGenericType_DerivedTypesAreRegistered()

   26       {

   27          // use a strict mock to ensure no other types are registered

   28          var container = MockRepository.GenerateStrictMock<UnityContainerBase>();

   29          container.Expect(x => x.RegisterType(typeof(ITestBase<A>), typeof(TestBaseWithInterfaceA))).Return(container);

   30          container.Expect(x => x.RegisterType(typeof(ITestBase<B>), typeof(TestBaseWithInterfaceB))).Return(container);

   31          container.RegisterAllTypesForOpenGeneric(typeof(ITestBase<>));

   32       }

   33    }

   34 

   35    public interface ITest<T> { }

   36    public class TestBase<T> { }

   37 

   38    public class TestA : TestBase<A>, ITest<A> { }

   39    public class TestB : TestBase<B>, ITest<B> { }

   40 

   41    public class A { }

   42    public class B { }

   43 

   44    public class TestBaseWithInterface<T> : ITestBase<T> { }

   45    public interface ITestBase<T> { }

   46    public class TestBaseWithInterfaceA : TestBaseWithInterface<A> { }

   47    public class TestBaseWithInterfaceB : TestBaseWithInterface<B> { }

 

Sorry about the formatting. Ergh. UPDATE: Formatting is still not ideal, I used CopySourceAsHTML plugin for VS2008. I can't install anything here at work, so no Live Writer :-\

Labels: ,

Wednesday, September 01, 2010

WPF Slowness and Unmanaged Debugging

Beat my head against a wall for a while today trying to figure out why our WPF application was running so slowly. Debugging, profiling, tracing, spelunking through file histories, all to no avail.

Turns out it was enabling unmanaged debugging in the project properties to use SOS.dll to trace some memory leak issues. This creates a HUGE performance overhead in WPF applications. Beware!

Labels: ,