Damon Payne: Hand waving software architect

103db signal to noise ratio at < .03% total harmonic distortion
Solution Architect, software developer, geek
Damon Payne at Blogged
2009 Microsoft MVP - Client App Dev
2007 Microsoft MVP - Solution Architecture
 Sunday, September 21, 2008

The AGT (Argentum Tela) series of articles is an effort to do two things. Usually an idea is presented only in its finished form. The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches. The second goal, and the example vehicle for the evolution aspect, is an extensible Design Surface for Silverlight similar to what we have in Visual Studio 2008. This type of application has all sorts of interesting uses. My example is a Home Theater layout tool. Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Visual Refactoring

Since this is a Silverlight application I thought I should spend some time making it look good. I hit my frustration limit in a very short period of time and what you see here is as far as I got. I am guessing Styling is not entirely baked in Silverlight 2 beta 2, or else doing a complete control template is really the way to go.

My first issue was with fonts. I downloaded a copy of the Trajan Regular font. Ever since Klipsch started using Trajan pro in the Palladium branding I’ve been digging the Trajan font family. At any rate, it seems that Silverlight is very picky about using extra fonts, be they set from a style or per control. Worse, it’s very difficult to track down where the issue might be. I have three primary tools available to me for Silverlight debugging: Blend 2.5 June CTP, VS2008 SP1, and running the application for inspection. Debugging is not fun when all three tools show different output, check out the ToolboxView:

clip_image002

Blend shows the correct font and color. VS2008 shows the correct nothing. Runtime shows the correct color but not font. I’ve tried obvious things like double checking relative paths and so forth. At this point I’m admitting defeat and moving on. At least my bad taste and visual look stolen from Klipschcorner’s CSS is better than black and grey. Right? Let’s skip to the punchline, here is what the application looks like now:

clip_image004

Couch++

I tricked a visual designer into making me a better purple couch. This person happens to be an extreme Adobe fanboy, to the degree that they didn’t believe me when I said there were other drawing programs for both vector and raster graphics. The Adobe fans are easily worse than the Mac fans. At any rate, that sure looks like a couch, at least. It’s rather large in relation to the design surface, but we’ll fix that with resizification later.

Speakers

I haven’t really thought of what all I want to include in the example HT Layout program, but I figured some speakers would be nice. I’m getting slightly better at drawing some things in Blend: these speakers look better than my original couch. If you’re not familiar with horn-loaded speakers you’ll have to trust me that the white horn shape is actually a reasonable caricature.

Conclusion

I’ll refactor later as I get to read more about the control templating and style creation. I think the app is starting to look like a real program, and we’re still less than 1000 lines of code. The next articles are not written yet, but the next step is to implement functionality that allows me to move, resize, and otherwise Transform things once they are on the designer surface. As it turns out, this is a very interesting problem for all sorts of reasons. I’m not breaking my Reality Blogging pledge, but remember I’ve done this in WinForms before, and I recall things like “selection” being more complex than it sounds: http://msdn.microsoft.com/en-us/library/system.componentmodel.design.iselectionservice_members.aspx . Once selection is implemented moving and resizing come free in WinForms, and I’ve got to build those from scratch now. I’m sure I’ll be spending some time in traffic this week and I’ll spend many mental cycles thinking about the interactions.

Source Code:DamonPayne.AGT[9].zip (1.26 MB)



Sunday, September 21, 2008 7:25:35 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback

This article and AGT[8] were written with Windows Live Writer, after Larry talked me into trying it.  So far, I really like the idea, but the implementation could be better.  I typically write my articles in Word 2007, since I may be working on one for days or weeks.  Cut 'n pasting out of Word into the DasBlog FreeTextBox just works.  Sure, it generates the ugliest HTML you've ever seen, but it looks like code in both IE7 and FF3.  Copy/pasting out of VS2008 into Live Writer looks like this:

ToolboxItem speakItem = new ToolboxItem("Tower speaker", "This is a generic 2-way tower speaker with horn-loaded mid & high range", typeof(HornSpeaker));
Toolbox.AddItem(speakItem, "Audio");

Copy/pasting out of MS Word 2007 into Live Writer looks like this, using the "keep formatting" option.

            ToolboxItem speakItem = new ToolboxItem("Tower speaker", "This is a generic 2-way tower speaker with horn-loaded mid & high range", typeof(HornSpeaker));

            Toolbox.AddItem(speakItem, "Audio");

It's not bad, but it insists on inserting some extra spaces between lines.  I've also been uploading a .zip file of the source code as it stands at the end of each article, and I find no way to do this from Live Writer - perhaps that's not supported by the blogger API.  I do like it inserting & uploading images for me.

For complex articles, I'll still be copy/pasting from Word, but for a free program I do rather like Live Writer.



Sunday, September 21, 2008 7:16:10 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [3]  |  Trackback

The AGT (Argentum Tela) series of articles is an effort to do two things.  Usually an idea is presented only in its finished form.  The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches.  The second goal, and the example vehicle for the evolution aspect, is an extensible design-time environment similar to what we have in Visual Studio 2008.  This type of application has all sorts of interesting uses.  My example is a Home Theater layout tool.  Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Code Refactoring

I’m eager to get on to some of the cool next steps like the ability to move and resize things on the Design Surface, but my TODOs are starting to pile up.  I’d rather not get too far into this and find that some fundamental thing that was bothering me is now a real issue.  Using the Task List feature in VS2008, I’ve got 20 things I should at least look at.

Namespaces

I’ve been thinking lately about some other Silverlight projects I have on the back burner, and how nice it would be to keep them in mind for the IoC stuff.  Therefore, I should rename DamonPayne.AGT.IoC to just DamonPayne.AG.IoC.  I like the fact that VS2008 makes the default namespace of a project match the project name, but the tooling stops there.  I have to rename the project, edit the default namespace, edit the assembly name, and do a global find/replace on the top level namespace.  Lame.  58 occurances replaced, and the Design and HTLayout projects reflect the new name; it even built the first time.

Events

While sitting in traffic I had the idea to overload += for my AggregateEvent<T> and make it feel more like a built in .NET event type.  As it turns out this won’t work the way I wanted it too so I erased that TODO.  I also got rid of the static “Test” method in EventAggregator.

Reflection

I have several TODOs related to reflection code.  The first one suggests Caching Type and Property information to make reflection go faster.  I’ll leave that alone for now and come back to it.

Tidy up: I found that there is a Type.EmptyTypes static var, similar to EventArgs.Empty.  I found three places where I could substitute Type.EmptyTypes.

I also found that I had some duplicate interface code and I could add some things to my TypeExtensions static class:

       public static bool ImplementsInterface(this Type t, Type intefaceType)

        {

            if (intefaceType.IsInterface)

            {

                Type[] interfaces = t.GetInterfaces();

                if (interfaces.Contains<Type>(intefaceType))

                {

                    return true;

                }

            }

            return false;

        }

 

        public static bool ImplementsInterface(this object o, Type intefaceType)

        {

            return ImplementsInterface(o.GetType(), intefaceType);

        }  

I was able to go through ServiceManager and ComponentBuilder and clean up some code using these Extension methods.

Several calls to invoking a Type’s default constructor can be replaced with Activator.CreateInstance; this was done throughout.  The 1-arg constructor for Presenter types was also replaced with a call to Activator.

Control Extensions

On suspicion that I would need the ability to scale controls without distorting their aspect ratio in the future, I left myself a note to create an extension method to determine an aspect ratio preserving method:

    public static class ControlExtensions

    {

        public static double UniformScaleAmount(this Control c, double maxDimension)

        {

            double originaltWidth = c.Width;

            double originalHeight = c.Height;

            double uniformScaleAmount = Math.Min(maxDimension / originaltWidth, maxDimension/ originalHeight);

            return uniformScaleAmount;

        }

    }

At this point, I am staring sideways with some dread at the remaining TODO items.  The remaining items involve:

1.       Revisit the relationship between ServiceManager and ComponentBuilder to see what, if anything, should be done about the crosstalk.

2.       The ToolboxCategory code doesn’t work how I’d like, and fixing it will involve a lot of digging deeper on the Silverlight control templating framework.

3.       There are several visual notes I’ve made to myself, I will address those in the next article.

4.       Something is amuck with InterfaceMocker, it only works once.

5.       I need to decide how I want configuration to work.

Configuration can have its own article I think, for now I’ll at least look into ServiceManager, ComponentBuilder, and InterfaceMocker.

Reflection Emit Redux

Inside ServiceManager.GenerateProxy, I did not take into account the fact that more than one client may ask for a given interface implementation.  In my startup code, I was able to get “Duplicate Type name in assembly” from time to time.  I just needed to add a check before building the type mock:

private static Dictionary<string, object> _proxies;

            string proxyName = t.Name+"TempProxy";

            if (_proxies.ContainsKey(proxyName))

            {

                return _proxies[proxyName];

            }

 

            object o = null;

            ModuleBuilder module = GetDynamicModuleBuilder();

            //

            TypeBuilder typeBuilder = module.DefineType(proxyName,

                TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.Class,typeof(object) );

            typeBuilder.AddInterfaceImplementation(t);

No more proxy errors.

ServiceManager loves ComponentBuilder

As soon as I introduced ComponentBuilder I should have moved all object creation code to it.  But I didn’t, so now here I am looking at several TODO items.  From ServiceManager.ObtainDefaultInstance:

                o = Activator.CreateInstance(t);

                //TODO: maybe use the ComponentBuilder to create the damn thing in the first place

                ComponentBuilder.ResolveServiceDependencies(o);

                ComponentBuilder.BuildPresenters(o);

ComponentBuilder.Create:

        public static T Create<T>() where T :new ()

        {

            T instance = new T();

 

            ResolveServiceDependencies(instance);

            BuildPresenters(instance);

            ServiceManager.ManageInstance(instance);//TODO: verify this was the right design choice later

 

            return instance;

        }

Furthur, ServiceManager.ManageInstance (which might have been a hairy issue otherwise) is used from only a single place, ComponentBuilder.Create.  Creating a non-generic override of Create is step 1:

        public static T Create<T>() where T :new ()

        {

            T instance = default(T);

            instance = (T)Create(typeof(T));          

            return instance;

        }

 

        public static object Create(Type t)

        {

            object instance = Activator.CreateInstance(t);

            ResolveServiceDependencies(instance);

            BuildPresenters(instance);

            return instance;

        }

I hate having to go back and write code that involves casting and Type, when generics are so much cleaner, but such is life.  While chasing down the resulting bugs, I realized Manage(List<Type> types) and ManageInstance(object provider) were almost the same method.  The Manage method is refactored to call ManageInstance:

        public static void Manage(List<Type> types)

        {

            Type baseServiceType = typeof(IService);

 

            foreach (Type t in types)

            {

                object instance = ObtainDefaultInstance(t);

                ManageInstance(instance);

            }

        }

Lovely, more TODOs off my list and some unintended good side effects as well.

Unit Testing

Unit Tests allow us to refactor with impunity.  The fact that this project was ~500 loc doesn’t hurt either.

I Google “Silverlight 2 beta 2 unit test” and look what I find: http://code.msdn.microsoft.com/silverlightut/Release/ProjectReleases.aspx?ReleaseId=1543

I have to admit I had been thinking about making my own or Porting XUnit, but now I don’t have to.  I’ve grown to like the minimalistic XUnit interface, and I feel blind without NCover, but this will do for now.

Source code: DamonPayne.AGT[8].zip (622.87 KB)



Sunday, September 21, 2008 6:32:39 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, September 20, 2008

The AGT (Argentum Tela) series of articles is an effort to do two things.  Usually an idea is presented only in its finished form.  The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches.  The second goal, and the example vehicle for the evolution aspect, is an extensible design-time environment similar to what we have in Visual Studio 2008.  This type of application has all sorts of interesting uses.  My example is a Home Theater layout tool.  Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Part 8 in a 50 part series begins...

Drag and Drop

It’s time to try dragging something out of the Toolbox and onto the DesignSurface.

We start dragging by wiring up events inside the ToolboxCategoryControl.  We’ve already established a mechanism for making sure only one ToolboxItem is ever selected, and that the ToolboxView owns the ToolboxCategoryControl.  We define a normal local dragstart event:

        void cat_DragStart(object sender, EventArgs e)

        {

            ToolboxItem tbi = SelectedItem;//Will already be populated from event wireup

            DragDropManager.BeginDrag(tbi);

        }

I have implemented the cleverly named DefaultDragDropManager in the DamonPayne.AGT.Design.Services namespace to handle the task.  The first thing DDDM does is obtain a drag-time representation of the Control visual.  This is one of the places where we start diverging more and more from how VS2008 works and looks today. While I’m not ready for the Visual Refactoring stage yet, we can clearly do better than a tiny mouse cursor with a “+” next to it.  This is what IDragTypeCreator is for: to provide a pluggable mechanism for building a better representation of what you’re dragging around than a mouse cursor.  I created a special DragContainer control for this purpose in DamonPayne.AGT.Design.Controls.  Here is the entire DefaultDragTypeCreator.CreateDragRepresentation method:

        public Control CreateDragRepresentation(Type t)

        {

            //Default behavior:

            DragContainer dc = new DragContainer();

            Control c = (Control)Activator.CreateInstance(t);

            //Thanks to http://www.jeffblankenburg.com/2008/04/how-about-some-code-simple-resizing-in.html for scaling code

            //TODO, extension method for uniform scale size?

            double originaltWidth = c.Width;

            double originalHeight = c.Height;

            double uniformScaleAmount = Math.Min(MAX_DIMENSION / originaltWidth, MAX_DIMENSION / originalHeight);

            ScaleTransform st = new ScaleTransform();

            st.ScaleX = uniformScaleAmount;

            st.ScaleY = uniformScaleAmount;

            c.RenderTransform = st;

            c.InvalidateMeasure();           

            c.UpdateLayout();

           

            //TODO: why couldn't I force this to recalc size here after setting render transform?

            double estimatedNewWidth = c.Width * uniformScaleAmount;

            double estimatedNewHeight = c.Height * uniformScaleAmount;

            double left = (dc.Width / 2.0D) - (estimatedNewWidth / 2.0D);

            double top = (dc.Height / 2.0D) - (estimatedNewHeight / 2.0D);

            c.SetValue(Canvas.LeftProperty, left);

            c.SetValue(Canvas.TopProperty, top);

            dc.LayoutRoot.Children.Add(c);

            dc.Opacity = .65D;

            dc.LayoutRoot.Opacity = .65D;

           

            return dc;

        }

I am basically creating an instance of whatever Type I was given, which ultimately came from ToolboxItem.Type.  Then I scale the instance down to where it will fit in my DragContainer and return the DragContainer.  With this in hand, DefaultDragDropManager wires up the mouse events for dragging around: basically when mouse left button goes up we do a hit check to see if there is an IDropTarget registered with us that would be under the current mouse position.  With the events set, we add the DragContainer control to the root visual of the Silverlight application.

Design Surface

The next thing I need to actually implement is the DesignSurface control, implementing IDropTarget.   This needs to be added into the IRegionManager way back when the ToolboxView and MessageConsole are created.  I’ve resized the whole Page such that I can fit a 480x640 gray DesignSurface in there.  You can now see me take my drag-time couch representation over to the design surface:

As soon as I got into developing the drop part, I realized I was in the Silverlight world, thinking like a WinForms developer.  Silverlight has built in hit test code already and I don’t need to do anything with Bounds.  The IDropTarget interface is thefore modified to use UIElement.HitTest(Point), so the EndDrag method can now do this:

        public virtual void EndDrag(MouseButtonEventArgs e)

        {

            RegionManager.TopLevelContainer.Children.Remove(_dragRepresentation);

            _dragRepresentation = null;

           

            foreach (IDropTarget target in _dropTargets)

            {

                if (target.IsHitTestVisible)

                {

                    IEnumerable<UIElement> elements = target.HitTest(_mousePos);

                    if (elements.GetEnumerator().MoveNext())//hit test succeed

                    {

                        IDesignableControl ctrl = DesignCreator.CreateInstance(_draggingType);

                        target.OnDrop(ctrl);

                    }

                }

            }

_draggingType = null;

        }

As soon as we enter OnDrop, the design time representation is worthless and we throw it away.  We’ll either be building the real control the surface or simply cleaning up.  I believe in the last article I described the interaction as the DesignSurface calling the creation method from OnDrop, but it makes more sense to put it here now.    For now, the IDesignTypeCreator simply instantiates the appropriate Type.  DesignSurface.OnDrop is incredibly simple for now:

        public void OnDrop(IDesignableControl dc)

        {

            dc.Visual.SetValue(Canvas.LeftProperty, _localMousePos.X);

            dc.Visual.SetValue(Canvas.TopProperty, _localMousePos.Y);

            LayoutRoot.Children.Add(dc.Visual);

        }

Success!  Here’s the very nice looking purple couch on the design surface.

Clearly there is tons of work to be done still, but I was shocked when I actually ran metrics: this just a little over 500 lines of code so far!

Source code: DamonPayne.AGT[7].zip (613.16 KB)



Saturday, September 20, 2008 1:06:22 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, September 18, 2008

The AGT (Argentum Tela) series of articles is an effort to do two things.  Usually an idea is presented only in its finished form.  The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches.  The second goal, and the example vehicle for the evolution aspect, is an extensible design-time environment similar to what we have in Visual Studio 2008.  This type of application has all sorts of interesting uses.  My example is a Home Theater layout tool.  Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Designer surface interactions

My goal now is to actually start thinking about creating and designing things.  The preferred means of using this is as follows:

1.       From the toolbox I start dragging something out towards the Great Wide Open.

2.       Somehow visually indicate that I am dragging something.

3.       When I let go, see where I have dropped what I was dragging.

4.       If what I dropped upon was something that cares about being dropped on, do something useful like create a design-time representation of the thinger.

Some “improved” traffic patterns downtown where I work has left me with a lot of time to think about design interactions on my way home every day.  As I’m coming to expect, every single thing related to Drag ‘n drop in WPF or WinForms is not in Silverlight, but we can start defining some constructs of our own.  I’m adding a Design Solution Folder, within which will be a StarUML project.  Sometimes it’s better to explain using pictures.

  

1.       IToolboxService should use IDragDropManager to indicate that Drag operation is beginning.

2.       IDragDropManager will query the IToolboxService to determine what is the type of the dragging item.

3.       IDragDropManager will use IDragTypeCreator to build some type of visual representation to indicate where the dragging item is.  It will attach some events to this Control and place it as a child of the RootVisal of the IRgeionManager, in the front of the Z-order.

4.       The end of a drag/drop will be determined by the events attached to the Control, such as Left mouse button up.

5.       IDragDropManager will query all the IDropTarget instances registered with it.  If the Location of the where the dragging Control was dropped falls within the Bounds of one, it will call that instances OnDrop event with the original ToolboxItem.  This allows the IDropTarget to do whatever it wants using the original information.  Otherwise, the drag representation will be destroyed by IDragDropManager.

6.       In our case, if we successfully drop on top of the visual representation of a DesignSurface instance, DesignSurface will use IDesignTypeCreator to create the final design-time representation of the IDesignableControl.  This allows different visuals and behaviors to be attached such as adorners for resizing and registration with various other design-time services.

 

I am nearly certain I am going to have to change RootVisual of IRegionManager to be a Panel rather than UIElement.  UIElement has no “children” collection for me to use for my drag-representation.  Based on some things I want to support later (alignment snap lines, possible extra adorners) the DesignSurface is ultimately going to have to be a base type or implement some kind of interface with some kind of collection of “filters” or IDesignSurfaceBehavior implementations.

The source code as of the end of this article contains stubbed out unfunctional versions of the interfaces mentioned here. In the next article, we’ll actually try to drag/drop around a purple couch.  After that we’ll spend some time doing code refactoring (the TODO are building up) and some visual refactoring before moving on to more complex interactions.

Source code: DamonPayne.AGT[6].zip (598.45 KB)



Thursday, September 18, 2008 7:43:00 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback

The RSS aggregators chopped off AGT[4], probably for being too long.  Still, you'll want to read #4 since we make huge progress in that article.  AGT[5] deals with the wild tangent involving dynamic proxy generation with Reflection Emit.

AGT[4] http://www.damonpayne.com/2008/09/18/RunTimeIsDesignTimeForAGT4.aspx

AGT[5] http://www.damonpayne.com/2008/09/18/RunTimeIsDesignTimeForAGT5.aspx



Thursday, September 18, 2008 5:42:43 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback

The AGT (Argentum Tela) series of articles is an effort to do two things.  Usually an idea is presented only in its finished form.  The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches.  The second goal, and the example vehicle for the evolution aspect, is an extensible design-time environment similar to what we have in Visual Studio 2008.  This type of application has all sorts of interesting uses.  My example is a Home Theater layout tool.  Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Tangent: Dynamic proxy generation in Silverlight using Reflection Emit

In the last article I made mention of a tangent, an evil waste of time.  If a component asks for an IService implementation that cannot be found, I started out throwing an exception saying so.  Then I found a situation where I wanted to allow a Service to be registered after it was needed, and only have an exception be thrown if the missing service was accesses before it could be somehow injected later.  This is the solution.

While I’m not very interested in Dynamic Languages right now, I am reaping the benefits of Microsoft’s attention to them.  Without consideration for the DLR in Silverlight, I doubt they would have included such a complete Reflection Emit implementation.

ServiceManager

We started out with a ServiceManager.Resovle method that looked like this:

        public static object Resolve(Type t)

        {

            object svc = null;

            if (_services.ContainsKey(t))

            {

                svc = _services[t];

            }

            else

            {

                throw new NotSupportedException(string.Format("A provider for {0} was not found", t));

            }

            return svc;

        }

We need to replace what’s in the else clause and make ServiceManager and ComponentBuilder a little smarter.  The first step is to create a way to keep track of the situation inside ComponentBuilder:

        /// <summary>

        /// Key=IService type, value=list of objects waiting on that IService

        /// </summary>

        private static Dictionary<Type, List<object>> _lateBinding;

        static ComponentBuilder()

        {

            _lateBinding = new Dictionary<Type, List<object>>();

        }

                {

                    object svc = null;

                    try

                    {

                        svc = ServiceManager.Resolve(propType);

                    }

                    catch (NoImplementationException)//TODO: fix this so an exception is not thrown?

                    {

                        svc = SetupLateBinding(propType, component);

                    }

        private static object SetupLateBinding(Type interfaceType, object client)

        {

            object svc = InterfaceMocker.GenerateProxy(interfaceType);

 

            if (!LateBinding.ContainsKey(interfaceType))

            {

                LateBinding.Add(interfaceType, new List<object>());

            }

 

            LateBinding[interfaceType].Add(client);

 

            return svc;

        }

We change the ServiceManager to throw NoImplementationException instead of NotSupportedException.  When ServiceManager is given something new to Manage now, we check to see if anyone out there was waiting on a service of this type:

        private static void CheckLateBinding(Type interfaceType, object provider)

        {

            if (ComponentBuilder.LateBinding.ContainsKey(interfaceType))

            {

                List<object> clients = ComponentBuilder.LateBinding[interfaceType];

                foreach (object c in clients)

                {

                    var propQuery = from p in c.GetType().GetProperties().AsQueryable<PropertyInfo>()

                                    where p.PropertyType == interfaceType

                                    select p;

                    foreach (PropertyInfo propInfo in propQuery)

                    {

                        propInfo.SetValue(c, provider, null);

                    }

                }

                ComponentBuilder.LateBinding.Remove(interfaceType);

            }

        }

 

 

TypeMocker

The magic of all the code shown above is contained in TypeMocker.  Our goal is this: given an Interface type we cannot find an implementation for, make up a very simple placeholder one which could potentially do something useful if we call methods on it.  Unfortunately the most useful things raise more issues than they solve in .NET:

·         I don’t have pointers here, so I can’t very well try to replace “this”, nor get at the enclosing object instance to do any sneaky replacement.

·         If I wanted to do a delegation model, where the proxy ultimately just obtained a ‘normal’ instance and delegated to that via inheritance or something, those methods would need to be virtual and I don’t want to force that on users of this library, especially myself.

The first thing we need to be able to do is create the assembly. You may recognize the name from the Badge of Honor article.

        private static ModuleBuilder GetDynamicModuleBuilder()

        {

            if (null == _dynamicModuleBuilder)

            {

                AppDomain currentDomain = AppDomain.CurrentDomain;

                AssemblyName proxyName = new AssemblyName("DamonPayne.IoC.TempProxy");

                AssemblyBuilder aBuilder = currentDomain.DefineDynamicAssembly(proxyName, AssemblyBuilderAccess.Run);

                //

                ModuleBuilder module = aBuilder.DefineDynamicModule(proxyName.Name);

                _dynamicProxyAssembly = aBuilder;

                _dynamicModuleBuilder = module;

            }

 

            return _dynamicModuleBuilder;

        }

 

        private static AssemblyBuilder _dynamicProxyAssembly;

        private static ModuleBuilder _dynamicModuleBuilder;

Now we can work on dynamically creating a class that implements an interface in GenerateProxy:

        public static object GenerateProxy(Type t)

        {

            if(!t.IsInterface)

            {

                throw new ArgumentException(t + " Is not an interface");

            }

            //Useful:

            //http://msdn.microsoft.com/en-us/library/3y322t50(VS.95).aspx

            object o = null;

            ModuleBuilder module = GetDynamicModuleBuilder();

            //

            TypeBuilder typeBuilder = module.DefineType(t.Name+"TempProxy",

                TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.Class,typeof(object) );

            typeBuilder.AddInterfaceImplementation(t);

We create a class that extends Object and implements interface “t”.  Because we are writing IL ourselves, lots of things that would ordinarily be done by the compiler have to be taken into consideration.  This includes calling the base class constructor from within our own:

            ConstructorBuilder conBuilder =

                typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.SpecialName, CallingConventions.Standard, Type.EmptyTypes);//TODO: use Type.EmptyTypes elsewhere!

            //Define the reflection ConstructorInfor for System.Object

            ConstructorInfo conObj = typeof(object).GetConstructor(new Type[0]);

 

            //call constructor of base object

            ILGenerator il = conBuilder.GetILGenerator();

            il.Emit(OpCodes.Ldarg_0);

            il.Emit(OpCodes.Call, conObj);

            il.Emit(OpCodes.Ret);

This next bit is tedious but easy to understand once you know what you’re trying to do.  Create a method on my new type for each interface method I need to implement.  The implementation currently just throws an exception saying that our attempt to allow friendly late binding failed:

            List<MethodInfo> interfaceMethods = new List<MethodInfo>();

            interfaceMethods.AddRange(t.GetMethods());

 

            Type[] extraInterfaces = t.GetInterfaces();

            foreach (Type extraIface in extraInterfaces)

            {

                interfaceMethods.AddRange(extraIface.GetMethods());

            }

 

            foreach (MethodInfo method in interfaceMethods)

            {

                ParameterInfo[] mParams = method.GetParameters();

                Type[] paramTypes = new Type[mParams.Length];

                for(int i = 0; i < mParams.Length; ++i)

                {

                    paramTypes[i] = mParams[i].ParameterType;

                }

 

                MethodBuilder methodBuilder =

                    typeBuilder.DefineMethod(method.Name,

                    MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.SpecialName, method.ReturnType, paramTypes);

               

                ILGenerator ilGen = methodBuilder.GetILGenerator();

                if (method.Name.Equals("Startup") || method.Name.Equals("Shutdown")) //TODO: dehackify this

                {

                    ilGen.Emit(OpCodes.Ret);

                }

                else

                {

                    ilGen.ThrowException(typeof(NoImplementationException));

                }               

            }

 

            Type finalType = typeBuilder.CreateType();

 

            o = Activator.CreateInstance(finalType);//TODO: replace other default constructor code with Activator

 

            return o;

There’s probably some work to do here to make sure attempts at creating  a proxy for the same type more than once are handled and so forth, but I’ll get to that when I decide on a unit test platform.  For now, its solving my late order-of-creation problems and would event support a circular dependency should one arrive.  My region manager/Page startup now goes through this sequence:

1.       We ask ServiceManager to handle Page, which is an IRegionManager.

2.       Page contains a RootPresenter, RootPresenter is created and needs an IToolboxService.

3.       IToolboxService is not found, but we get a dynamically created IToolboxServiceTempProxy instead.

4.       The UserControl_Loaded event of Page is called, which creates the toolbox service.

5.       Page gets a real IToolboxService implementation and everyone is happy.

At the end of this article, I am clearly not happy with the relationship between ComponentBuilder and ServiceManager.  I’m going to have to fix that, but first I want to get some more work done on my actual problem domain.

 

The source code is the same as what I posted for AGT[4].



Thursday, September 18, 2008 3:28:26 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback

The AGT (Argentum Tela) series of articles is an effort to do two things.  Usually an idea is presented only in its finished form.  The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches.  The second goal, and the example vehicle for the evolution aspect, is an extensible design-time environment similar to what we have in Visual Studio 2008.  This type of application has all sorts of interesting uses.  My example is a Home Theater layout tool.  Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Toolbox Service UI

It is now time to do some slightly more meaningful XAML work and create the visual representation of the toolbox service: this is where we’ll stow the designable components and drag them off onto the yet-to-be-created designer surface.  I am NOT going to worry about making it look snappy until later.

In order to test the ToolboxView, I have created the first designable item.  It is a big purple “Couch”.  I must stress to you that it does look like a couch.  It’s purple and has cushions, as anyone can clearly see.

 

What did I tell you?  Couchtastic.  I’m working on getting a better XAML couch or finding some patience to draw a better one.  This will be good enough to test with.

Looking back at the previous article, I chose to support a categorized toolbox like VS2008.  Therefore I’m going to make another UserControl called ToolboxCategory which is simply a heading stating the category name and a ListBox full of some representation of the ToolboxItems.  Simple XAML for the Category to start with:

<UserControl x:Class="DamonPayne.HTLayout.Controls.ToolboxCategoryControl"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Width="205" Height="Auto">

    <Grid x:Name="LayoutRoot" Background="White">

        <Grid.RowDefinitions>

            <RowDefinition></RowDefinition>

            <RowDefinition></RowDefinition>

        </Grid.RowDefinitions>

        <TextBlock x:Name="_categoryHeader" Grid.Row="0">Category Header</TextBlock>

        <ListBox x:Name="_itemLst" Grid.Row="1" DisplayMemberPath="Name">           

        </ListBox>

    </Grid>

</UserControl>

I’ll add some public properties to ToolboxCategoryControl to communicate with its parent.  I’m not ready to rewrite Silverlight data binding so I’ll have to make some concessions.  I’ll go ahead and start writing the little code I need to populate the IToolboxService.

Create the ToolboxView and hand it over to the region manager as soon as the Page (our entry point UserControl) is loaded:

            ToolboxView tbView = ComponentBuilder.Create<ToolboxView>();

            mgr.AddView(tbView, "Toolbox");

Create a RootDesignerPresenter to handle logic for the DamonPayne.HTLayout.Page:

        [Presenter()]

        public RootDesignerPresenter Presenter { get; set; }

             Presenter.InitializeDesignableControls(); …

When I run this code I realize I made a mistake earlier.  The whole point of making the ComponentBuilder helper methods internal and not private was to use them to wire-up dependencies from service types as I manage them in ServiceManager.  Adding these calls to ServiceManager.CreateDefaultInstance fixes the issue and I’ve added another todo item to take a look at this after I have some more real code.   

                //TODO: maybe use the ComponentBuilder to create the damn thing in the first place

                ComponentBuilder.ResolveServiceDependencies(o);

                ComponentBuilder.BuildPresenters(o);

And another mistake pops up when I run this code. Page is created on AppStartup.  Page depends on RootDesignerPresenter, which depends on IToolboxService.  The IToolboxSerivce implementation is also our ToolboxView UserControl, which does not get created until the Page.UserControl_Loaded event completes.  So while we are wiring up the dependencies for Page, we get “A provider for DamonPayne.AGT.Design.Contracts.IToolboxService was not found.”  Now the previous design decisions come back to haunt us again and I’m facing another round of decisions.

1.       I could build the UI components in the proper order in Application_Startup.  This requires me, the developer, to be smart about what depends on what.  In fact, this also begs the question of what to do later if I find that there is a circular dependency between services.

2.       Return to the idea of making a class that implements IToolboxService and interacts with the visual representation using this other mechanism. 

3.       Create a mechanism for late-binding IService implementations.  By this I mean, rather than throw an exception from ServiceManager.Resolve() if an implementation cannot be found, store the fact that I’m missing an implementation for a certain interface on a certain type and inject this IService later if it becomes available.

4.       Make ServiceManager smarter.  Suppose we gave ServiceManager 100 types to manage at once, and some of those had dependencies on each other.  We could make ServiceManager either build a dependency tree, or even easier, take multiple passes over the collection of 100 types in a sort of poor-man’s (lame programmer’s) tree-flattening.

 

#1 would get me on my way the fastest, and also seems lame.  If I have circular dependencies, #1 will never work, although circular dependencies should be avoided.  I may also find myself spending a lot of time later keeping track of dependencies in my head and change the order of type registration around.

#2 will almost certainly just move the problem elsewhere, unless this new magical class does not have its visual representation provided to it as an automatic service.  This may be the cleanest option.

#4 might be useful on its own, but would also involve re-thinking how I create and manage Views and such.  I’m going to reject this one for now.

#3 has some appeal.  This would even allow for (accursed) circular dependencies.  The first drawback that comes to mind is that throwing an exception right away gives an immediate and unambiguous message that something is wrong and what that something is.  Attempting to use an IService that is waiting around for someone to create it by registering it with ServiceManager or ComponentBuidler would just result in a null reference – a ubiquitous and annoying exception.

There is an additional, and totally evil, option I could tack on to #3.  Silverlight is a partial implementation of the base class libraries we are used to, like the Compact Framework.  Because of this, one always has to go back and inspect class availability using Intellisense or the reference documentation.  Probably because of Silverlight’s dynamic language support – a fairly complete System.Reflection.Emit implementation is present.  In addition to remembering that I’m “waiting around for an ISuck implementation”, I could dynamically create a class that implements ISuck and throws an exception saying “Sorry, this is a placeholder and we never found an implementation for you” in case any methods are called before the implementation can be found. 

Using the great sanity check mechanism known as “Who’s on MSN Messenger” I happened to find a respectable software architect online to bounce this notion off of.  The conversation went something like this:

Damon: <explains situation and #3 solution>
Damon: So, is this overkill just to keep from throwing a null reference?

OtherDude: Uh, yeah, way overkill.  Save that for when your whole application works and you want to start gold-plating.  Version 3 or something.

Unfortunately I was 90% done with the reflection emit idea before this dissenting opinion arrived.  Honestly this was a ludicrous tangent but is also fun.  I will cover the solution in the next article.  Suffice to say that we are supporting Clever Late Binding for IService implementations and we can continue with the Toolbox Service.

The RootDesignerPresenter contains logic, such as “What am I putting in this toolbox?” For now I’ll only add one thing and be sure this all works.

        public void InitializeDesignableControls()

        {

            ToolboxItem couchItem = new ToolboxItem("Purple Couch", "This is clearly a couch", typeof(Couch));

            Toolbox.AddItem(couchItem, "Furniture");

        }

Making this work is painful because Silverlight does not support RelativeSource for data binding.  I can’t use a property on “this” for setting the Category Name TextBlock.  I’m now actually terrified of what I’m going to discover for data binding in Silverlight, but for now I’ll just make the property set the value. 

Of course the very next thing I try to do exposes another data binding shortcoming.  List<T> does not implement INotifyPropertyChange so that if I add a ToolBoxItem to a List<ToolBoxItem> which service as ItemsSource the GUI does not update itself.   I have three primary choices here.  I can build a special ScreenModel object for this screen which contains a List property I can fire INotifyPropertyChange for, I can try to implement a custom List<T> that does what I want, or I can mess with everything completely manually.  For now, I will use a ViewModel, which also erases my previous manual setting of the Category Name.  It’s worth reproducing the whole View Model here to point out how it’s implemented for automatic data binding goodness.

using System.Collections.ObjectModel;

using System.ComponentModel;

using DamonPayne.AGT.Design.Types;

 

namespace DamonPayne.HTLayout.ViewModels

{

    public class ToolboxCategoryModel : INotifyPropertyChanged

    {

        public ToolboxCategoryModel()

        {

            ToolboxItems = new ObservableCollection<ToolboxItem>();

        }

 

        private string _CategoryName;

        public string CategoryName

        {

            get { return _CategoryName; }

            set

            {

                _CategoryName = value;

                OnPropertyChanged("CategoryName");

            }

        }

 

        private ObservableCollection<ToolboxItem> _ToolboxItems;

        public ObservableCollection<ToolboxItem> ToolboxItems

        {

            get { return _ToolboxItems; }

            set

            {

                _ToolboxItems = value;

                OnPropertyChanged("ToolboxItems");

            }

        }

 

        public event PropertyChangedEventHandler PropertyChanged;

 

        public void OnPropertyChanged(string pname)

        {

            if (null != PropertyChanged)

            {

                PropertyChanged(this, new PropertyChangedEventArgs(pname));

            }

        }

    }

}

 INotifyPropertyChange does not work for collection types.  INotifyCollectionChanged  does not seem to be used by data binding if I put it on my ToolboxCategoryViewModel.  The answer is System.Collections.ObjectModel.ObservableCollection<T>, which implements INotifyCollectionChanged  in the way the data binding code in Silverlight is expecting .  I’ve made myself some code snippets for the INotifyPropertyChanged code since I suspect I’ll need them later.

For the basic implementation:

<?xml version="1.0" encoding="utf-8"?>

<CodeSnippets

    xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">

  <CodeSnippet Format="1.0.0">

    <Header>

      <Title>OnPropertyChanged</Title>

      <Author>DamonPayne.com</Author>

      <Description>Insert a default OnPropertyChanged method and INotifyPropertyChanged event</Description>

      <Shortcut>OnPropertyChanged</Shortcut>

    </Header>

    <Snippet>

      <Code Language="CSharp">

        <![CDATA[

        public event PropertyChangedEventHandler PropertyChanged;       

       

        protected void OnPropertyChanged(string pname)

        {

            if (null != PropertyChanged)

            {

                PropertyChanged(this, new PropertyChangedEventArgs(pname));

            }

        }       

        ]]>

      </Code>

    </Snippet>

  </CodeSnippet>

</CodeSnippets>

 

Per property:

<?xml version="1.0" encoding="utf-8" ?>

<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">

    <CodeSnippet Format="1.0.0">

        <Header>

            <Title>INotifyPropertyChanged property</Title>

            <Shortcut>inotifyprop</Shortcut>

            <Description>INotifyPropertyChanged prop, assumes OnPropertyChanged</Description>

            <Author>DamonPayne.com</Author>

            <SnippetTypes>

                <SnippetType>Expansion</SnippetType>

            </SnippetTypes>

        </Header>

        <Snippet>

            <Declarations>

                <Literal>

                    <ID>type</ID>

                    <ToolTip>Property Type</ToolTip>

                    <Default>string</Default>

                </Literal>

                <Literal>

                    <ID>property</ID>

                    <ToolTip>Property Name</ToolTip>

                    <Default>BindingProperty</Default>

                </Literal>

            </Declarations>

            <Code Language="csharp">

                <![CDATA[

 

private $type$ _$property$;

public $type$ $property$

{

    get { return _$property$; }

            set

            {

                  _$property$ = value;

      OnPropertyChanged("$property$");

            }

}

$end$]]>

            </Code>

        </Snippet>

    </CodeSnippet>

</CodeSnippets>

 

Next I’ll add some Item selection code using my event aggregator.  I’m going to define a generic SelectedDataChangedEvent:

    public class SelectedDataChangedEvent<T>:AggregateEvent<T>

    {

        public T Payload { get; set; }

    }

Now my constructor for the View Model looks like this:

        public ToolboxCategoryModel()

        {

            ToolboxItems = new ObservableCollection<ToolboxItem>();

            _selectionEvent = EventAggregator.Get<SelectedDataChangedEvent<ToolboxItem>, ToolboxItem>();

            _selectionEvent.Subscribe(item => { SelectedToolboxItem = null; }, item => !ToolboxItems.Contains(item));

        }

 

        private SelectedDataChangedEvent<ToolboxItem> _selectionEvent;

Behold the simple power of the event filters.  These two lambdas just say “If anyone anywhere else selects a toolbox item that is not part of my collection, I’ll be a nice citizen and clear my own selection.”  The selected item now participates in data binding AND event aggregation and it feels cleaner than I expected:

SelectedItem="{Binding Path=SelectedToolboxItem, Mode=TwoWay}"

        private ToolboxItem _SelectedToolboxItem;

        public ToolboxItem SelectedToolboxItem

        {

            get { return _SelectedToolboxItem; }

            set

            {

                _SelectedToolboxItem = value;

                OnPropertyChanged("SelectedToolboxItem");

                if (null != value)

                {

                    _selectionEvent.Raise(value);

                }

            }

        }

Back in the real IToolboxService implementation, we need to subscribe to this event too.  And now we have a toolbox service with gui!

 

It doesn’t look like much, but in the future there will be some “visual refactoring” going on.  I’ll sure miss my awesome purple couch though.

Conclusion

This step ended up being very long since there were several rabbit holes to go down.  We’ve created a Toolbox service, proven the EventAggregator is going to work, learned some things about Silverlight data binding I didn’t know before, and introduced the concept of the View Model into our lexicon.  In the next few steps, things will get really interesting!

Source code: DamonPayne.AGT[4].zip (571.61 KB)



Thursday, September 18, 2008 3:26:29 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, September 16, 2008

You simply know you're doing good, important, awesome work when you are able to get this error at runtime:

An exception of type 'System.Security.VerificationException' occurred in DamonPayne.IoC.TempProxy but was not handled in user code

Additional information: Operation could destabilize the runtime.

The Type name "DamonPayne.IoC.TempProxy" is wrong, and doesn't exist, which just adds to the fun. This will factor into the AGT series of articles, but I took a brief break to share this badge of honor.  In the age of awesome search engines, a developer can often learn how to quickly do a search for their particular error type or error message or get lucky based on some aspect of their exception stack trace.  Sometimes, very rarely (rarely unless you are Dan) you will have an error so specific that no one has blogged about it, or documented it, or asked about it in newsgroups.  The first reaction to this situation is typically panic or disgust; "crap I'm in uncharted territory" or "I can't believe no one else has tried this".  Sometimes these feelings are followed by Pride.  In a time of rising water level, more and more abstractions between the programmer and the metal, there is a certain appeal to doing something that was clearly not intended by the developers of the frameworks you are consuming.  At the very least, you now know that you are down in the bowels of The Machine, far below the safety nets installed to save Mort from himself.



Monday, September 15, 2008 11:06:11 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, September 15, 2008

If you’re just jumping in, you may want to start from the beginning: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Beginning the Designer

In case you’re not pouring over the source code with interest and reverence, let’s take a quick snapshot of the structure that is emerging:

There’s very little in the IoC or HTLayout projects so far, but it seems very clean up to this point.  I have also done nearly nothing related to my core problem of a Design Time environment for Silverlight: the Design project stands empty.  It seems sensible enough to work from left to right for the time being, so let’s begin with the Toolbox. 

Designable

The next step is to create an abstraction for what we are going to be working with.  In the VS2008 design time environment the coin of the realm is the System.ComponentModel.Component.  In many ways I didn’t like this since one is nearly always casting Component to Control.  Creating an interface that gives us a grammar for something which is “designable” and also has a visual representation will be a better place to start.

namespace DamonPayne.AGT.Design

{

    public interface IDesignableControl

    {

        /// <summary>

        /// Visual representation of this IDesignableControl

        /// </summary>

        Type VisualType { get; }

 

        /// <summary>

        ///

        /// </summary>

        bool Scalable { get; }

 

        /// <summary>

        /// Should the designer allow transformations such as rotation to be applied?

        /// </summary>

        bool Transformable { get; }

 

        string Name { get; set; }

    }

}

That’s all I’ve got for now.  Clearly I’ve thought this through…

Toolbox Service

A toolbox is a thing that displays a list of things you can drag out into another thing.  It is a thing as well as a meta-thing.  Beginning in Visual Studio 2005 we had the notion of a categorized toolbox.  I like that, so the next step is to decide on the starting point for a Toolbox service.  Keeping with the Microsoft design for now, I create a ToolboxItem.

namespace DamonPayne.AGT.Design.Types

{

    public class ToolboxItem

    {

        public ToolboxItem():this("Unknown", "No description",null)

        {

        }

 

        public ToolboxItem(string name, string desc, Type type)

        {

            Name = name;

            Description = desc;

            Type = type;

        }

 

 

        public string Name { get; set; }

        public string Description { get; set; }

        public Type Type { get; set; }

    }

}

The IToolboxService is straightforward.

namespace DamonPayne.AGT.Design.Contracts

{

    public interface IToolboxService : IService

    {

        void AddItem(ToolboxItem item);

        void AddItem(ToolboxItem item, string category);

        ToolboxItem SelectedItem { get; }

        void RemoveItem(ToolboxItem item);

    }

}

That will serve for now.  Before I get into creating some funky purple couches and speakers in Expression Blend, I need to make sure my framework supports my next intended action.

    public partial class ToolboxView : UserControl, IView, IToolboxService

It makes a lot of sense for the visual toolbox UserControl to implement the IToolboxService interface.  Who better?  Now I need to take a look at my framework already.  Things that I need to create as top level objects go through the ControlBuilder.  Things that need to provide service implementations to other components are created when their Type is registered with the ServiceManager.  I’m trying to have it both ways and I can’t without doing more work.  Since I envision the same situation for the designer surface and property grid later on this deserves some thought.

1.       I could create a non-visual toolbox class that knows about the ToolboxView and have this class implement the IToolboxService instead.  The ToolboxView would have to provide public methods for all the appropriate operations.

2.       In addition to #1, I could change ToolboxView to have a “Visual” property that could be set at a later time.

3.       I could change ServiceManager such that the ToolboxView (while implementing IToolboxService) is actually instantiated up front just like other service providers and somehow requested.

4.       I could strengthen the loving relationship between ComponentBuilder and ServiceManager.

Recall the public interface to ComponentBuilder:

public static T Create<T>() where T :new ()

I could fairly easily detect here that I’ve been asked to create something which is potentially both a service provider and service consumer and pass it off to ServiceManager after fully building it.  Unless I receive one metric ton of hatemail, I will take this approach for now.  ComponentBuilder can call this entirely new ServiceManager.ManageInstance method:

        public static void ManageInstance(object provider)

        {

            Type baseServiceType = typeof(IService);

            Type t = provider.GetType();

            Type[] interfaces = t.GetInterfaces();

            foreach (Type iface in interfaces)

            {

                if (iface.InterfaceExtends(baseServiceType))

                {

                    _services.Add(iface, provider);

                }

            }

        }

The main issue that I can foresee is getting into trouble with multiple instances of an IService being provided by different Types.  If this situation arises, some form of discriminator will need to be introduced.  For now, though, this is a good stopping point.  In the next article we can begin the visual implementation of the ToolboxView.

Source code: DamonPayne.AGT[3].zip (672.51 KB)



Monday, September 15, 2008 7:30:55 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback

Some news aggregators (Google reader) like to just ignore articles from DasBlog if they get too long, or perhaps it doens't like the special formatting HTML I get when copy/pasting out of Word.  At any rate, if you are following the AGT series, please check out

AGT[1] http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT1.aspx (Composite UI and modules)

and

AGT[2] http://www.damonpayne.com/2008/09/15/RunTimeIsDesignTimeForAGT2.aspx (Service wire-up, presenters, and Events)

I will keep my eye on Google Reader and be sure to double post.  I think I've been singled out for this behavior for my Break Up Google article.



Monday, September 15, 2008 8:42:22 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, September 14, 2008

If you are just joining, you might want to start from the beginning: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Service Wire-up, Presenters, and Events

As I wrapped up the last article I found that I needed to determine a mechanism for providing IService implementations to Components that need them, and that it would be nice to have this happen in some automatic repeatable fashion.  As for providing IService implementations, there are four ways (four that come to mind right now anyway) to do this, one of which I have already shown:

1.       Explicitly: ISuck is = ServiceManager.Resolve<ISuck>();

2.       Implicit magic: public ISuck MySuck{get;set;} //set by some magic

3.       Via constructor: public MyServicedComponent(ISuck defaultSuck){…} //possibly also set by magic

4.       Via a Serviced Component interface: perhaps something like this, coupled with a registration mechanism:

    public interface IServicedComponent

    {

        IService[] GetDependencies();

        void SetDependency(Type serviceType, IService impl);

    }

In terms of discoverability of what is going on, #4 wins.  Back in my original design goals I stated that I wanted things to feel like Serviced Components.  An interface like this, which we could build on, would establish an unambiguous set of expectations and behaviors.  When it gets down to the other design consideration of “How do I want to code?”, though, I’m not very in love with #4.  #1 is safe but puts any future lifecycle management we may want to do out of reach most likely.  To support #2 or #3, I am going to need control over when most important objects are created.  It seems that going with #3 would make the various Reflection code that I have and expect I’ll have later a bit more messy.  As much as it pains me to do so, I’m going to go with #2 and try to make sure I take care of some design goals:

·         Make the source of injected objects as discoverable as seems reasonable, so that there is as little distrustful magic as possible.

·         In terms of the cleanest OO practices one doesn’t want to allow objects to exist in a state where they are invalid.  Providing a default constructor when this would render an object unusable is not desirable. 

Since I’ve been rereading some Fundamental Material lately, the answer has already jumped out at me.

Builder Pattern

The Builder Pattern separates the construction of a complex object from its representation so that the same construction process can create different representations.

Using a builder pattern we can separate the construction of a serviced component from the creation of its dependent parts.  This also provides a clean “entry point” into the creation of top level objects and gives client code a window into when and how dependency injection is happening without exposing any unnecessary plumbing.  For truly old-school OO folks: I realize I am reaching a bit here as what I’m about to show differs in structure but not intent from the canonical Builder examples.

Because generics are the answer to nearly everything, and because part of the point of this series of articles is to show code evolving, I type the following code into VS2008 and stare at it so that thoughts can congeal.

namespace DamonPayne.AGT.IoC

{

    public class ComponentBuilder

    {

 

        public static T Create<T>() where T :new ()

        {

            T instance = new T();

 

            return instance;

        }

I thought about this for a while.  Suppose my first use of this code was as follows:

MessageConsoleView view = ComponentBuilder.Create<MessageConsoleView>();

This will accomplish several goals for me.   If MessageConsoleView needs an IService implementation I can detect that need and provide it here.  If MessageConsoleView needs a “Presenter” of some kind I could detect and provide that too.  In the first article I stated that I wanted as little code behind/presenter code as possible.  As it turns out, I had been corrupted by WPF.  WPF contains a nice notion of a Command infrastructure whereby visual components can be bound to fire commands such as from a button’s click event.  This often results in hardly any code behind or presenter needed.  Silverlight doesn’t have this, nor a Navigation service, nor control Validation plumbing, so there’s probably some more work to do later.

I could take this notion one layer “forward”, and come up with a way to construct the IView implementations too, such that the entire composite UI was constructed in magical fashion. For now I’ll stick with imperative creation of the IViews.  The following code now works:

        private void UserControl_Loaded(object sender, RoutedEventArgs e)

        {

            IRegionManager mgr = ServiceManager.Resolve<IRegionManager>();

            MessageConsoleView view = ComponentBuilder.Create<MessageConsoleView>();

            mgr.AddView(view, "MessageConsole");

        }

The next step is to determine what the contract looks is for a serviced component to say “I need an IService implementation”.  Since we have ruled out the constructor method, we’re left with properties or fields.  Now to rely solely on reflection or include attributes too?  For now, we’ll just let the magic roll and state that: Any Public properties of type IService or some Presenter type will just be set for you within ControlBuilder.  MessageConsoleView needs an ILogService.

public ILogService LogService { get; set; }

We’ll assume we can use the LogService property as soon as the Constructor returns, like so:

        private void UserControl_Loaded(object sender, RoutedEventArgs e)

        {

            LogService.Debug("Message console started");

        }

Next it’s up to the ComponentBuilder to make the magic happen.  As soon as we generically create an instance of whatever type was given to ComponentBuilder we call an method to find out if it needs any IService types:

        internal static void ResolveServiceDependencies(object component)

        {

            PropertyInfo[] publicProps = component.GetType().GetProperties();//TODO: cache per Type to make this faster

            foreach (PropertyInfo pi in publicProps)

            {

                Type propType = pi.PropertyType;

                if (propType.IsInterface && propType.InterfaceExtends(typeof(IService)))

                {

                    object svc = ServiceManager.Resolve(propType);

                    pi.SetValue(component, svc, null);

                    ResolveServiceDependencies(svc);//TODO: Smartest way to do this?

                }

            }

        }

“InterfaceExtends” is a new extension method for Type “Type” from the new TypeExtensions static class in the IoC project.  Determining if one Interface extends another interface is rather annoying so it’s encapsulated there.  Other than that this method is straightforward: look for any public properties on component that are of a Type that extends IService.  Resolve that type using the ServiceManager and recursively check to see if that service depends on any other services.  I also had to refactor ServiceManager to have a Resolve(Type) method alongside the generic Resolve<Type>() method.  This takes care of IService injection for now, on to Presenters.

I could call Presenters a special kind of Service and be done now.  I won’t do this for several reasons.  First, I’ve never looked back on code and wished I could swap out a different Presenter implementation.  While running automated testing, why would I want to swap out a Presenter?  If I’m not testing the logic/process, and I’m mocking out any heavy components like data access, what am I really testing then?  Second, I tend to like doing Model-View-Presenter a certain way which doesn’t fit into some of the design choices I made for the IService world and I don’t want to redo my IService world for this reason at least.  I like to have a Presenter talk to a certain specific View interface, while the View knows the concrete type of the Presenter.  View ßà Presenter communication is then a combination of method calls and data binding. 

I could have an IPresenter interface and use that to type public properties and have the same logic as I have above.  Since every Presenter will be highly specialized I would end up just having IPresenter as a “marker” interface and since this is .NET there are better ways to do this.  I could force a Presenter to extend a base class, but in this case I don’t like that either.  It’s a common practice to have an application specific Presenter base class to use for code sharing.  I’ll mark a Presenter with a public Property with a certain attribute type on it.  I can always change my mind later.  After creating an empty IMessageView and MessagePresenter, MessageConsoleView now has another Property:

        [Presenter()]

        public MessagePresenter Presenter { get; set; }

And my presenter constructor looks like:

    public class MessagePresenter

    {

        public MessagePresenter(IMessageView view)

        {

            View = view;

        }

Now I can go back to ComponentBuilder and add another method:

        internal static void BuildPresenters(object component)

        {

            PropertyInfo[] publicProps = component.GetType().GetProperties();//TODO: cache per Type to make this faster

            foreach (PropertyInfo pi in publicProps)

            {

                object[] attrs = pi.GetCustomAttributes(typeof(PresenterAttribute), true);

                if (null != attrs && attrs.Length > 0)

                {

                    //We rely on the convention that the Presenter has a public constructor with a view as argument,

                    //where said view is implemented by "component"

                    ConstructorInfo ci = pi.PropertyType.GetConstructor( new Type[] { component.GetType() } );

                    object presenter = ci.Invoke(new object[] { component });

                    pi.SetValue(component, presenter, null);

                    ResolveServiceDependencies(presenter);

                }

            }

        }

At this point, by the time my IView loaded event fires, I’ve already got valid state through the friendly ComponentBuilder.  The “parts” of my Builder pattern are the IServices and Presenters.  If I were a tiny bit less lazy I could hide the algorithms for IService and Presenter resolution behind an interface or Strategy and allow different algorithms to be plugged in for resolution. 

 

Component Communication using Events

“Every problem in computer science can be solved by one more level of indirection.”

In Composite Application Guidance for WPF (http://msdn.microsoft.com/en-us/library/cc707857.aspx) they introduce the idea of an Event Aggregator.  An Event Aggregator is sort of a message hub.  In normal .Net event driven code, you have a component that has a hard reference to another component that can raise an event.  The event is signified as a special delegate type and VS2008 is nice about generating code stubs for you.  The problem here is that in complex systems you might be interested in certain occurrences where it is impossible or undesirable to obtain references to all of the components that could affect the kind of occurrence you are interested in.  An Event Aggregator is a huge help in meeting the design goal of having components communicate with each other.

The PRISM way of doing this is to define a special event for absolutely every action that could occur and hooking these into an event aggregator.  This might mean (going back to the purple couch example from the previous article) a CouchAddedEvent, a CouchChangedEvent, and a CouchDeletedEvent all with a Couch payload.  Following this will surely be a ChairAddedEvent, ChairChangedEvent, ChairDeletedEvent, and so forth.  In order to avoid this event explosion, we can define more generic events with template data payloads.  The first place I’ll use this is for the ILogService.  I’m going to refactor the ILogService slightly to show two points:

    public interface ILogService: IService

    {

        void Log(DamonPayne.AGT.IoC.Types.LogMessage m);

    }

The new Types namespace will contain things like this.  Using the EventAggregator I want to be able to get an event of a certain type, with a certain kind of data payload and either subscribe to it or raise the event with a valid payload.  I don’t see any way to make these work exactly the same as the .NET events you might be used to, so let’s take a look.  First we create an AggregateEvent class to help with the generics programming. 

namespace DamonPayne.AGT.IoC.Events

{

    public class AggregateEvent<T>

    {

        public AggregateEvent()

        {

            _subscribers = new Dictionary<Action<T>, Func<T, bool>>();

        }

 

        internal void InvokeAll(T arg)

        {

            foreach (Action<T> callback in _subscribers.Keys)

            {

                if (null == _subscribers[callback] || _subscribers[callback](arg))

                {

                    callback(arg);

                }

            }

        }

 

        private Dictionary<Action<T>, Func<T, bool>> _subscribers;

 

 

        public void Subscribe(Action<T> callback)

        {

            Subscribe(callback, null);

        }

 

        public void Subscribe(Action<T> callback, Func<T, bool> filter)

        {

            _subscribers.Add(callback, filter);

        }

 

        public void Raise(T payload)

        {

            InvokeAll(payload);

        }

 

    }

}

Generics are still the answer to everything as far as I can tell.  It took some time to get the template parameters correct, but now the EventAggregator thus far is fairly simple.

namespace DamonPayne.AGT.IoC.Events

{

    /// <summary>

    /// Allow creation and subscription to decoupled events

    /// </summary>

    public class EventAggregator

    {

        static EventAggregator()

        {

            _events = new Dictionary<Type, object>();

        }

        private static Dictionary<Type, object> _events;

 

        /// <summary>

        /// Get an event representation. The event Type signifies the sort of situation that we are interested in raising or being notified of,

        /// and the payload type represents the precise type of data payload we are interested in.

        /// </summary>

        /// <typeparam name="TEventType"></typeparam>

        /// <typeparam name="TPayload"></typeparam>

        /// <returns></returns>

        public static TEventType Get<TEventType, TPayload>() where TEventType: AggregateEvent<TPayload>

        {           

            Type t = typeof(TEventType);

            if (!_events.ContainsKey(t))

            {

                ConstructorInfo noArgs = t.GetConstructor(new Type[] { });

                TEventType evnt = (TEventType)noArgs.Invoke(null);

                _events.Add(t, evnt);

            }

 

            return (TEventType)_events[t];

        }

The first example of using the event aggregator is in the ILogService implementation, MemoryLogger.  I realize I had Startup and Shutdown methods on IService but wasn’t using them, so a call to Startup was added to ServiceManager.ObtainDefaultInstance.  The MemoryLogger wants to be able to let the universe know when log messages arrive, in a decoupled fashion.  The event “Type” is MessageArrivedEvent.

    public class MessageArrivedEvent<T> : AggregateEvent<T>

    {

        public T Message { get; set; }

    }

Next we get an event that has the type of payload we are interested in.

        private MessageArrivedEvent<LogMessage> _logEvent;

 

        public void Startup()

        {

            _logEvent = EventAggregator.Get<MessageArrivedEvent<LogMessage>,LogMessage>();           

        }

 

        public void Log(DamonPayne.AGT.IoC.Types.LogMessage m)

        {

            _messages.Add(m);

            _logEvent.Raise(m);

        }

This is the code necessary to consume this event in MessageConsoleView.

        public MessageConsoleView()

        {

            InitializeComponent();

            _currentMessages = new List<LogMessage>();

            DataContext = _currentMessages;

            EventAggregator.Get<MessageArrivedEvent<LogMessage>, LogMessage>()

                .Subscribe(MessagePosted);

        }

 

        private void MessagePosted(LogMessage m)

        {

            _currentMessages.Add(m);

        }

We would need to keep the event around in order to unsubscribe later, but we haven’t gotten that far yet.  There is one other bit of functionality that I wanted to show here that isn’t used yet but is best shown along with the rest of the EventAggregator code.  We also have the notion of event filters, implemented using … wait for it… Generics.  We have the ability to subscribe to an event conditionally.  This is another slick idea stolen from PRISM.  Take a look at this temporary test method:

        public static void Test()

        {

            MessageArrivedEvent<LogMessage> myEvent =

                EventAggregator.Get<MessageArrivedEvent<LogMessage>,LogMessage>();

 

            Action<LogMessage> logCallback = msg =>

            {

                Console.WriteLine("I am the first subscriber");

            };

 

            Action<LogMessage> lc2 = msg =>

            {

                Console.WriteLine("I am the second subscriber!");

            };

 

            Action<LogMessage> filterCB = msg =>

            {

                Console.WriteLine("I only get called if the message sucks");

            };

 

            myEvent.Subscribe(logCallback);

            myEvent.Subscribe(lc2);

            myEvent.Subscribe(filterCB, lm =>  lm.Message.IndexOf("suck") != -1);

 

            LogMessage goodMsg = new LogMessage

            {

                Level = LogLevels.Debug,

                Message = "Yee haw!"

            };

 

            LogMessage suckMsg = new LogMessage

            {

                Level = LogLevels.Debug,

                Message = "this sucks!"

            };

 

            myEvent.Raise(goodMsg);

            myEvent.Raise(suckMsg);                       

        }

We subscribe to the MessageArrivedEvent<LogMessage> with three different Closures.  For the third closure, we use the overload that accepts a Func<T,bool>.  The lambda expression only returns true if the message contains “suck” in it somewhere.  Running this code shows that when we raise the event with goodMsg only logCallback and lc2 fire.  Raising the event with suckMsg passes the filter and all three callbacks fire.  This is incredibly useful to further fine tune which events a component is really interested in.

Summary and Next Steps

Service containers, service locators, model-view-presenter, and event aggregation actually have very little to do with the overall problem I set out to solve.  I could have made a service container specific to the design-time environment similar to what Winforms 2.0 uses and gotten started on the core problem sooner.  Still, this stuff may come in handy.  I have now the beginnings of a framework that I can use and refine as I discover what my needs truly are.

Source code: DamonPayne.AGT[2].zip (550.62 KB)



Sunday, September 14, 2008 8:55:10 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [3]  |  Trackback

If you are just joining, you might want to start from the beginning: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Layouts and Modules

I’m about to steal some ideas that are in common use, ideas from PRISM, Castle Windsor, the Visual Studio design-time environment, and a thousand other things.  I’ll briefly explain some of the core concepts here.

Modules or Services

In a well designed Windows Forms application, one would have a proper separation of concerns.  Suppose my form was for place orders for big purple couches.  I would have a CouchOrderForm that implements ICouchOrderView with very little logic: populating values or potential values only, perhaps with Data Binding, and event handlers.  These event handlers would delegate the actual work to a CouchOrderPresenter of some kind.  CouchOrderPresenter would probably use to a CouchOrderDataAccess class or perhaps a CouchBussinessProcess class to accomplish the necessary tasks, and update the UI using a combination of data binding and events.  I know people who would frown upon this as “primitive”, but even getting this far would be miles ahead of the average .NET project I saw as a consultant.

For testability, this design accomplishes a fair bit of concern-separating.  I can test almost my entire program without messing around with “how do I test the logic that’s in the Form?”  For example, I have often created a unit test class that implements the ICouchOrderView interface and does asserts in the various callback.  This means that a database and whatever other “real” components are required must be present and that might be very Heavy for unit test time.  If my code was written to use ICouchDataAccess instead of CouchOrderDataAccess, it’s suddenly much easier to mock out parts of my framework.  I might also be able to supply different ICouchDataAccess implementations at run time if that makes sense for my program – though I think this need is often horribly misunderstood and over used by many advocates. 

When I originally encountered this idea we called it the Service Locator Pattern in Java.  The term “service” is a loaded word.  I used to ask interview questions along the lines of “What is a Class? Now what is an object?  Now what is a Component?  Now what is a Service?”  I would change terminology here to say “module” or “strategy”, but Service is the commonly known semantic of our times, so I’ll use service to talk about program chunks that are essentially managed components.  My Component Container/Service Locator will be a ServiceManager.  It might be useful to have some common behaviors for these components, so IService will be the base interface for components.

When I add these things to the IoC project, I notice that when I choose to Add à new item, “Interface” is not an option for Silverlight projects.  Doesn’t MSFT want us to take Silverlight seriously?

The idea is that the ServiceManager will figure out what classes are available when a component asks for an IFoo implementation.  I’ve seen lots of fascinating ways of doing this in Full Framework projects.  Config files, loading every assembly in a certain directory, manually resolving at program startup, and others.  In Silverlight, the AppManifest.xml file contains a “Deployment.Parts” tag, which contains all the assemblies that get deployed with your app.  Still, I don’t seem to be able to call Assembly.Load() on these, so for now I’m going to go with manual resolution at program startup.

Generics make getting started on a service locator a breeze:

    public class ServiceManager

    {

        static ServiceManager()

        {

            _services = new Dictionary<Type, object>();

        }

 

        private static Dictionary<Type, object> _services;

 

        /// <summary>

        /// Pass in a list of strong types and determine what service interfaces they provide to us:

        /// </summary>

        /// <param name="types"></param>

        public static void Manage(List<Type> types)

        {

            Type baseServiceType = typeof(IService);

 

            foreach (Type t in types)

            {

                Type[] interfaces = t.GetInterfaces();

                foreach (Type iface in interfaces)

                {

                    if(iface != baseServiceType)

                    {

                        Type svcInterface = iface.GetInterface("DamonPayne.AGT.IoC.IService", false);

                        if (null != svcInterface)//We know this interface extends IService

                        {

                            _services.Add(iface, ObtainDefaultInstance(t));

                        }

                    }

                }

            }

        }

 

        /// <summary>

        /// Since an object could implement more than one interface, we may have in in here under multiple keys

        /// </summary>

        /// <param name="t"></param>

        /// <returns></returns>

        protected static object ObtainDefaultInstance(Type t)

        {

            object o = null;

            var q = from val in _services.Values.AsQueryable<object>()

                    where val.GetType().IsAssignableFrom(t)

                    select val;

 

            o = q.FirstOrDefault<object>();

            if (null == o)

            {

                Type[] noArg = new Type[0];

                o = t.GetConstructor(noArg).Invoke(null);

            }

 

            return o;

        }

 

        public static TServiceType Resolve<TServiceType>()

        {

            TServiceType svc = default(TServiceType);

            Type t = typeof(TServiceType);

            if (_services.ContainsKey(t))

            {

                svc = (TServiceType)_services[t];

            }

            else

            {

                throw new NotSupportedException(string.Format("A provider for {0} was not found", t));

            }

            return svc;

        }

 

 

    }

Now I need something to use to test this out.  I think I might want a Logging service of some kind to display messages to me, so I’ll create an ILogService interface in the IoC project:

    public interface ILogService: IService

    {

        void Debug(string message);

    }

 

And I’ll need to provide an implementation somewhere.  For now I’ll add a folder/namespace to the Layout project and create a simple do-nothing implementation.  In the Application_Startup event handler I can now start setting things up.  I create a MemoryLogger and:

        private void Application_Startup(object sender, StartupEventArgs e)

        {

            this.RootVisual = new Page();

            List<Type> s = new List<Type>

            {

                typeof(MemoryLogger)

            };

            ServiceManager.Manage(s);

 

            ILogService logger = ServiceManager.Resolve<ILogService>();

            //success!

        }

Now I’m starting to get somewhere.  I’m planning on creating an implicit way to get these services later.  There seems to be two schools of thought here: setting services on serviced components using a property or field, and supplying all the necessary services in the constructor.  For my next step, though, I want to get some things on the screen to help visualize how this is going to fit together.

Composite UI

My notion of a Region Manager is stolen directly from “Composite Application Guidance for WPF”.  We can abstract out the idea of a Window and various views and evolve the idea of how the UI should function over time.  I know that I will have the notion of a View, which is docked into a Region, which is managed by a RegionManager of some kind.  First, we think about these interactions and come up with a first try at interfaces.  Just to start getting some things on the screen, a View will be just this:

    public interface IView

    {

        /// <summary>

        /// Grid, etc. extends canvas

        /// </summary>

        Canvas LayoutRoot { get; }

    }

I’m not sure that I need an explicit implementation of a Region, so my IRegionManager consists of the following:

    public interface IRegionManager : IService

    {

  UIElement RootVisual { get; }

        List<string> RegionNames { get; }

        void AddView(IView v);

        void AddView(IView v, string regionName);

        IView GetView(string regionName);

        List<IView> Views { get; }

    }

The IRegionManager implementation does what I need it to do for now.  Clearly, our Page is a suitable class for serving as the Region Manager.  In the last article I envisioned three regions, but now that I’ve got my logging idea I’ll extend it to four.  I need a region for a Toolbox, Designer Surface, Property Grid, and Message Console.  Implementing the IRegionManager interface and supplying some default content to be sure I’m laying things out the way I want, the XAML and runtime application looks like so:

<UserControl x:Class="DamonPayne.HTLayout.Page"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Width="800" Height="600">

    <Canvas x:Name="LayoutRoot" Background="White">

        <Grid x:Name="_regionArea" Background="Red" Width="800" Height="600">

            <Grid.RowDefinitions>

                <RowDefinition></RowDefinition>

                <RowDefinition></RowDefinition>

            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>

                <ColumnDefinition></ColumnDefinition>

                <ColumnDefinition></ColumnDefinition>

                <ColumnDefinition></ColumnDefinition>

            </Grid.ColumnDefinitions>

            <Canvas x:Name="Toolbox" Grid.Row="0" Grid.Column="0" Width="Auto">               

                <TextBlock>I am toolbox</TextBlock>

            </Canvas>

            <Canvas x:Name="DesignSurface" Grid.Row="0" Grid.Column="1" Width="Auto">

                <TextBlock>I am design surface</TextBlock>

            </Canvas>

            <Canvas x:Name="PropertyGrid" Grid.Row="0" Grid.Column="2" Width="Auto">

                <TextBlock>I am property grid</TextBlock>

            </Canvas>

            <Canvas x:Name="MessageConsole" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3">

                <TextBlock>I am the message console</TextBlock>

            </Canvas>

        </Grid>

    </Canvas>

The IRegionManager implementation is incredibly straightforward and in the source code at the end of this article.  Applying some refactoring we get the ServiceManager to create the Page for us and the application startup now looks like this:

        private void Application_Startup(object sender, StartupEventArgs e)

        {           

            List<Type> s = new List<Type>

            {

                typeof(MemoryLogger),

                typeof(Page)

            };

            ServiceManager.Manage(s);

 

            IRegionManager mgr = ServiceManager.Resolve<IRegionManager>();

            RootVisual = mgr.RootVisual;

            //success!

        }

The next thing to decide is how IViews get loaded into our IRegionManager on startup.  It would be nice if I could use the same mechanism for IService wire-up, but this article is getting a bit long already.   For now, I’m going to create the visual design for the message console to set up the next article.  I create a Controls folder/namespace to hold my application specific UI components and put a MessageConsoleView in.  This component will be a UserControl that implements IView.  As soon as I implemented IView, however, I see that LayoutRoot was a poor choice of name since it forced an explicit interface implementation, so I refactor to IView.VisualRoot instead.  I also see that when I said “Canvas” was a good root because Canvas and Grid derived, I meant “UserControl”, so I refactor that too.

Now I have something to think about for the next article.  The MessageConsoleView will obviously need to get at my ILogService implementation…

Licensing

Now that I’ve got some code in here, I should decide on how I’m going to share that.  The Creative Commons license seems to fit my goals.  I’m not super up to date on open source license wording, but this one will do for now, in code-snippet form:

<?xml version="1.0" encoding="utf-8"?>

<CodeSnippets

    xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">

  <CodeSnippet Format="1.0.0">

    <Header>

      <Title>

        Creative Commons License

      </Title>

    </Header>

    <Snippet>

      <Code Language="CSharp">

        <![CDATA[

/*

Creative Commons - attribution-noncommerical-share alike 3.0 Unported

          You are free to copy, distribute, and transmit this work.

          You are free to adapt the work.

        Under the following conditions:

          -You must attribute the author(Damon Payne, http://www.damonpayne.com) for this work but not in a way

          that suggests the author endorses you or your use of the work.

          -You may not use this work for commercial purposes

          -If you alter, transform, or build upon this work, you are free to distribute the work under the same or similar license to this one.

*/

        ]]>

      </Code>

    </Snippet>

  </CodeSnippet>

</CodeSnippets>

If anyone out there wants to provide input on this license, please do.

Source code throug this article: DamonPayne.AGT[1].zip (538.15 KB)



Sunday, September 14, 2008 3:12:17 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback

Often times, the act of explaining a question out loud to another person involves a lot of complex and fleeting thought, we think at over 600 words per minute, and coalescing into sentences for the transmission from mental constructs to speech.  The thought process involved in this preparation for vocalization often restructures the problem in such a way that the question is answered in the asking.  An early mentor of mine called this effect “Talking to the bear”; he had a teddy bear on top of his monitor who served as a sounding board for his toughest issues, and later my issues as well. 

For a while, I’ve wanted to do some Reality Blogging.  Take a complex idea and a set of design goals, state them out loud, and slowly work towards a completed product or module.  Often times, I have presented an idea in, say, eight parts, because the idea was large enough to warrant breaking up for explanation.  The idea was fully baked before the first part was published.  The notion here, rather, is not to complete the idea but rather to work with both Visual Studio and Word open; to state design goals and see how they pan out later, to see how easy it was to refactor, to see a complex idea emerge out of nothing.

The Goal

The goal is to have an extensible, lightweight design surface and design-time environment for Silverlight.  As I have written about in the past (http://www.damonpayne.com/2007/04/24/Designer0.aspx) there are any number of neat reasons for which it would be useful to have  design time capabilities at runtime in applications.  My example application will be a Home Theater Layout application for Silverlight.  The vision is something like this:

So, I want this to be able to work in a manner we are familiar with: I drag things out of a toolbox onto a design surface, where I am allowed to drag and resize things.  When I select things I will be able to edit the selected item using a property grid.  I’ll want to support limited undo and be able to select multiple things to move around and so forth.

 In Windows forms, you can host the designer in your own application though it’s a lot of work. When the time came to make tradeoffs, the WPF designer “Cider” was not made hostable outside of Visual Studio.  Besides, there is no PropertyGrid for Silverlight, and no <<lots of other stuff>> for Silverlight, so this is really a big effort. 

Silver is Argentum in Latin, ergo its period table symbol is AG.  Ergo is also Latin, how fun.  Anyway, all the cool kids abbreviate Silverlight as “AG” and nothing sensible like “SL”.  The Latin word for “design” is more or less tela.  I dub thee, The ArGentum Tela project, or AGT for short. 

Design Goals

As Anders Heijlsberg said way back when he was famous for something called Delphi, it’s good to start out with some goals, it’s good to think about “how do I want people to use this?”  I have some design goals and functional requirements:

·         I want different aspects of the UI to function independent of each other

·         I want to be able to swap out different implementations for any aspects of the program that makes sense for

·         I want component to component communication to happen without components having references to each other

·         I want the building blocks of my program to feel like Serviced Components

·         I want to be able to serialize the results of my designer surface for later retrieval

·         I want a healthy # of common tasks accessible through the keyboard

·         I want this to work on the Mac.  I thought everyone was running Windows by now but apparently there are literally dozens of Mac users out there, so I should take their poor incomplete keyboards into account.

·         I want to package this as a reusable design-time library with a Reference Implementation – the home theater layout tool

·         I want to have as little code-behind/presenter as possible

I’ve been re-reading my GoF book, arguing with Dan almost every day, and reviewing the way the PRISM code looks.  I have some ideas about how I want to accomplish all of this.  As of now, my solution looks like this then:

·         DamonPayne.AGT

o   DamonPayne.HTLayout – the Silverlight sample project

o   HTLayoutWeb – a web test project for HTLayout

o   DamonPayne.AGT.IoC – how’s that for a name?  I’m going to pursue some inversion of control concepts for Silverlight, and that stuff will live in this assembly.

o   DamonPayne.AGT.Design – the code that makes the designer work will live here.

 

What’s next?

I’ve got Word open and Visual Studio open; it’s time to get started.  Where to begin?  In the next article we’ll start exploring some basic concepts for layouts and components.  Want to play along?  I’ll post the current source code at the end of each step.

 DamonPayne.AGT[0].zip (515.64 KB)



Sunday, September 14, 2008 10:24:11 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [2]  |  Trackback