Odd designer behaviour...

The evil designer attribute ;o)

I'm working on a project at the moment where the client want's an
"Add-in" for an existing piece of software... it's a COM interop
project, .Net 2.0 (and yes, it uses Castle, IoC sits in
nicely with
the IServiceProvider :) and it
hosts a custom designer, and the add-ins must exist in their own
directory, outside of the host applications base directory.

At any rate, it's been working just fine so far, but today I was
trying to introduce some custom designers... and they weren't
being constructed... which highlighted some odd behaviour in the
design time support - I have 6 or so assemblies, most
are support assemblies, some containing controls and their
associated designers, something like this:

public class MyButtonDesigner :
ControlDesigner { ..}

[Designer(typeof(MyButtonDesigner))]

public class MyCustomButton :
ButtonBase { .. }

And then there is the core assembly which hosts the design
surface etc. and contains a number of  COM-visible classes
- one of these class in the core assembly is
constructed via Com interop by it's Name, and everything starts
it's life from there in their Add-in, much like a Main class in a
WinForms project.

So the core assembly references the support assemblies, and has
no problem creating controls at runtime within these
assemblies...

But then...

However, the design time support fails to construct or make use
of the custom designers... and doesn't blow up, it just
fails silently - personally I hate this kind of behaviour...
I like things to fail fast, in your face :)

It appears the custom designer is never constructed because
the design time infrastructure fails to locate the
assembly it's held within, even though my code has
just created an instance of a control from the same said
assembly not an instant before... arghh!

To my mind this is madness... I'm not passing a string reference
to the type, and the assembly is already loaded, it should be as
simple as using the Type in the attribute to create an instance
of the designer - looking at the internal implementation of
this attribute, I can see where it all goes terribly wrong:

public DesignerAttribute(Type
designerType)

{

      this.designerTypeName =
designerType.AssemblyQualifiedName;

      this.designerBaseTypeName =
typeof(IDesigner).FullName;

}

It's still a puzzle as to why this isn't being resolved... the
assembly is already loaded against the current AppDomain - I
guess I could mess with the fusion logger to figure it out, there
must be some subtle different - but I didn't have the time to
waste, so I just cheated, implementing an
AppDomain.AssemblyResolve event handler to take
care of returning the assembly that's already loaded when
matching against a set of pre-loaded assemblies.

I think the silent failure is what annoys me the most, this is
something which could be easily introduced and might not be
imediately detected when performing a minor update... I'm still
not sure how I could write a test to detect it...

Speaking of custom designers... I'm unimpressed by how most
custom designers are marked internal... especially for classes
that are designed to be subclassed... why the hell is the
ButtonBaseDesigner marked internal?

Written on November 30, 2006