Friday, February 22, 2008

Scott Guthrie talks about silverlight 2.0 and it is looking to be exactly what I hoped it would be. It seems they are really aiming for enabling RIA applications, but cross platform, cross browser.

The big announcement is the inclusion of built-in controls. It was a big disappointment to me that they were not included in silverlight 1.0 or 1.1, but they are included now!

My take on this is that it will revolutionize the way we build software. As you might know, I've been involved in creating a big RIA application with xbap. Although it was great, we did not have a very good story on the use of the 'browser'. I was reminded time and time again that it was weird to use the browser, while it was not cross platform or even cross browser. We had good reasons to go for xbap none the less, but I'm looking forward to seeing what we can do with Silverlight 2.0.

Friday, February 22, 2008 9:28:46 PM (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback

I sometimes do it, but don't like to do it too often. But this one, I just want to archive here so I can always find it: Beatriz has just released a great ready-to-use drag and drop library. She has also written a terrific blog post about it here, that shows the steps she took to achieve it.

I just ran the project and it performs well, has insertion adorners and even allows dragging and dropping within the same list. Good stuff!

Friday, February 22, 2008 1:54:19 PM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback

This is the fourth of a series about using Workflow Foundation to control your UI Logic in a WPF application. The full table of contents:

  • Workflow as controller: Introducing <M,V,C> where M: ViewModel, V : WPF, C : WF
  • Part II, starting the application, and the adapter
  • Intermezzo: new sample application
  • Part III, your first view
  • Part IV, decoupling view from controller
  • Part V, marshalling commands from WPF to WF
  • Part VI, Injecting a controller in a subview / workspace
  • Part VII, IOC on the cheap: injecting and retrieving objects
  • Part VIII, Broadcasting for all to see
    Recap

    In the first post, the complete solution was presented. I am presenting a solution to use workflow as the controller part in your MVC inspired WPF application. It is inspired on the thought that you do not need complex frameworks, because WPF already gives you great power (routed eventing, resources). So, no IOC is used, no event aggregator etcetera: it's taken care of by WPF and WF, a natural fit.
    The solution is very decoupled and I feel it's a great advantage to be able to visual your control logic.
    In the previous post, I talked about the various ways to show a view, and actually already talked about the decoupling mechanism: commands.

  • I'm very lucky to have received some good comments from Wekemf about tight coupling. I urge you to read those comments and maybe chime in.

    In this post I will not return on that subject, but will quickly address two important activities that help in configuring your system quickly: the SetMainContent activity and the SetDataContext activity and sending WPF commands to WF's HandleCommand.

    SetMainContent activity

    A controller adapter is a normal WPF contentcontrol. It has the job to participate in the visual tree on behalf of our workflow controller class. To actually attach a view to it, we need to set it's content property.

    As shown in the previous post, you can just set on in xaml yourself, but it's more logical to let the workflow decide on the view. Ofcourse, the best approach is totally up to you.

    I usually use the stateinitalization activity to set up a view for us. I drag in the SetMainContent activity, and choose a type from the references assemblies.
    If it weren't for this step, the controller assembly would not need a reference to the view assembly at all. I found it very cool to be able to select a type with the typebrowser and just have it show up.

    The typebrowser is located in an assembly I have put in the externalAssemblies folder. It is a project, not started by me. The code did not work when I got my hands on it, but I managed to fix it by using a hammer. Check out this post to learn more about this great design-time experience!

    If you have a business need to decouple even further, you would need to adjust the SetMainContent activity, and instead of sending a real Type, send a string key or whatever. Then you would create some mapping functionality to map that key to the actual view.

    When the adapter get's notified by the SetMainContentMessage that it needs to set a content, it will just create the view (using reflection) and place it as it's own content.

    SetDataContext activity

    I do not like MVP at all, where the presenter talks back to the view directly (using an interface or something). I feel it's way too 'pushy' and way too much work. I believe in databinding (especially WPF bindings, I think Microsoft got it right this time). You view should just bind to your domain objects. In many cases, it's better to create a wrapper for the domainobjects, so you have the opportunity to supply some shortcut properties or view specific stuff: you might have a list of products, and you want the view to display the sum of the prices. That is a great opportunity for the viewmodel to expose a 'Sum' property that the view can simply bind to.

    The object that is used as a ViewModel should live with the controller who will be able to communicate with it.
    I usually create an internal public class, simply called ViewModel and have the controller inject that class with domain objects.

    The Set DataContext activity is very similar to the SetMainContent activity, in that it let's the adapter know it has to set a datacontext on itself.
    You configure the SetDataContext activity simply by choosing a field or property of your controller.

    In small sample applications, I have used the 'invoking' event, to hook up some code that actually initializes the ViewModel object.

    Sending WPF commands to the Workflow: HandleCommandActivity

    The HandleCommandActivity is really what makes using the solution so easy. I have blogged about it already extensively, and I will just summarize here:

    Workflow has a difficult communication story. You need to define your incoming and outgoing calls in an ExternalDataExchangeService. Then you have to hook up events in your workflow to listen to incoming calls/events. It is not possible to listen to the same events in two different states, without using the very difficult CorrelationTechnique.

    This is not necessary for our usage. I have created the HandleCommand activity to just listen to a queue with a specific name. That name is defined by the command we are listening to. So, if you want your workflow to react when you send it the string 'workflowRules', you would just drag in the HandleCommand and configure the Command property to read 'workflowRules'. No need to setup a special event for it.

    The commandService class has a PostCommand method, that you can call to put a message on the queue. That's all there is to it.

    So, when we receive a WPF command, we cast it to a RoutedUI command. The commandname is used to form a SimpleCommandMessage which can be used as input to the PostCommand method.

      1         #region command sinks
      2         private void CmdExecuted(object sender, ExecutedRoutedEventArgs e)
      3         {
      4             string commandname = (e.Command as RoutedUICommand).Name;
      5
      6             PostCommand(commandname, e.Parameter);
      7
      8         }
      9
    10         private void PostCommand(string commandname, object Parameter)
    11         {
    12             if (implementedCommands.Contains(commandname))
    13             {
    14                 commandSvc.PostCommand(new SimpleCommandMessage(instance.InstanceId, commandname, Parameter));
    15             }
    16         }
    17
    18         private void CmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
    19         {
    20             string commandName = (e.Command as RoutedUICommand).Name;
    21
    22             if (implementedCommands.Contains(commandName))
    23             {
    24                 e.CanExecute = commandSvc.CanExecute(new SimpleCommandMessage(instance.InstanceId, commandName));
    25             }
    26         }
    27
    28         #endregion

    As you can see, I first check if the workflow even implements such a command. If not, it would be too expensive to send it to the workflow.
    Also, check out the CmdCanExecute method. It actually makes it possible for the workflow to put rules on the HandleCommand activity that are used to figure out if a command can be executed. For instance, if you are not authorized to do something, the command was never in CanExecute, so the button that hooks up to it was always dimmed!

    I hope that clears up some questions. Let me know what you think!

    Friday, February 22, 2008 11:24:20 AM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback

    This is the fifth of a series about how to go about using postcompilation in your solutions. You can read it as a tutorial on how to use PostSharp. I am very much new to that framework, but the power it provides could seriously change how you build your applications. While working on the EF contrib project, I had to dive into PostSharp, and I hope to share some of the things I learned along the way.

    This post introduces the weaver, that will do exciting stuff for us.

    The full table of contents:

  • Introducing Entity Framework Contrib- Easy IPoco implementation V 0.1
  • Part II, Postsharp Core versus Postsharp Laos
  • Part III, the compound aspect
  • Part IV, the PocoInterfaceSubaspect (composition aspect)
  • Part V, hooking up the weaver
  • Part VI, the EdmScalarWeaver
    Recap

    We wish to create an attribute that can be placed on top of our ordinary Poco class, that will magically transform it into a class that implements the 3 IPoco interfaces. These are needed by the Entity Framework to do it's work. We will use PostSharp to do this.
    Our previous post talked about the compound attribute and how it goes about implementing interfaces on classes for you.

    This post will look at how we are going to hook up a weaver to do more complex stuff, not directly supported by the provided Laos aspects.

    But first I want to clear up a statement I made here: 'I found it wildly confusing the first time I came across the two parts of postsharp. Laos is such a high-level abstraction, that you use it quite differently from Core. In the latter, you have to spinup your own weaver, in Laos you do not ever see a weaver. '
    It is not true that you do not ever see a weaver when using Laos. I should have been more clear: Laos offers a great deal of functionality that you can use without going into a weaver.

    We want to put custom attributes on our type that EF needs (the EDM scalar attributes on top of properties and the EDM type attribute that connects your type to a EDM type). Laos does not seem to have a ready-to-use aspect that provides that functionality, so we are going to need to hook into the weaver ourselves! How exciting!
    Thankfully, we can derive from TypeLevelAspectWeaver to make life easy enough.

    Hooking up a weaver

    The cool thing about using the weaver is, that you can put it in it's own assembly and not have to reference it in the assemblies that you are postcompiling. That is quite important, because the weaver depends on PostSharp.Core and there is another license attached to it.
    The PocoAttribute adds an aspect to the collection, like it did for the other aspects:

      1 public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
      2         {
      3             // Get the target type.
      4             Type targetType = (Type)element;
      5
      6 ....
    10             // inspect the complete class and add EDM scalar attributes to the properties
    11             collection.AddAspect(targetType, new EDMAttributesSubAspect(this.EDMContainerName, Name, NamespaceName, PathToConfigFile));
    .....
    12 }

    At line 11, the EDMAttributesSubAspect is added. This means that when Laos is ready to start working, it will check that aspect to see what it should do. Let's look at it now:

        [Serializable]
        internal class EDMAttributesSubAspect : ILaosTypeLevelAspect
        {
            #region fields and properties
            internal string EDMContainerName { get; set; }

            internal string TypeName { get; set; }
            internal string NamespaceName { get; set; }
            internal string PathToConfigFile { get; set; }
            #endregion

            #region ctor
            /// <summary>
            /// ctor
            /// </summary>
            /// <param name="EDMContainerName">the container name</param>
            /// <param name="NamespaceName">namespacename, can be null</param>
            /// <param name="TypeName">typename, can be null</param>
            public EDMAttributesSubAspect(string EDMContainerName, string TypeName, string NamespaceName, string PathToConfigFile)
            {
                this.EDMContainerName = EDMContainerName;
                this.TypeName = TypeName;
                this.NamespaceName = NamespaceName;
                this.PathToConfigFile = PathToConfigFile;
            } 
            #endregion

            #region ILaosTypeLevelAspect Members

            public void CompileTimeInitialize(Type type)
            {
            }

            public bool CompileTimeValidate(Type type)
            {
                return true;
            }

            public void RuntimeInitialize(Type type)
            {
            }

            #endregion

            #region ILaosWeavableAspect Members

            public int AspectPriority
            {
                get { return int.MinValue; }
            }

            #endregion 

        }

    You might be surprised to hear that this is the complete aspect!! Nothing that hints at what is to come.

    When such a thing happens, you might be stumped. But obviously you will immediately think to check the assemblyinfo file of the PostSharp4EF assembly:

    [assembly: PostSharp.Extensibility.ReferencingAssembliesRequirePostSharp("PocoTypeWeaver", "EntityFrameworkContrib.PostSharp4EF.Weaver")]
    [assembly: InternalsVisibleTo("EntityFrameworkContrib.PostSharp4EF.Weaver")]

    Okay, I was kidding. You wouldn't have thought of that. ;-)

    The first statement there, instructs PostSharp to look for a plugin, with name PocoTypeWeaver to process all assemblies that are referencing this assembly. It is just another way of expressing requirements. I could have put that inside the attribute. But I did not.

    The plugin file can be found in the weaver assembly. It is just a normal text file with naming convention that matches the entire assembly name + "psplugin". The contents of that file:

    <?xml version="1.0" encoding="utf-8" ?>
    <PlugIn xmlns="http://schemas.postsharp.org/1.0/configuration">
      <TaskType Name="PocoTypeWeaver" 
                Implementation="EntityFrameworkContrib.PostSharp4EF.Weaver.PocoEDMAttributesWeaverFactory, EntityFrameworkContrib.PostSharp4EF.Weaver">
      </TaskType>
    </PlugIn>

    Here you will see a task PocoTypeWeaver and a reference to an implementation of a weaver factory. So, our PocoAttribute needs the pocoTypeWeaver and it can get one through the use of a factory. But, since your client assembly will not have a reference to this weaver assembly (which contains this mapping file), we need some way to tell it where to look. Enter the psproj file that was put inside your client assembly:

    <Project xmlns="http://schemas.postsharp.org/1.0/configuration">
    	<SearchPath Directory="../EntityFrameworkContrib.PostSharp4EF.Weaver/bin/{$Configuration}"/>
    	<SearchPath Directory="{$SearchPath}" />
    	<Tasks>
    		<AutoDetect />
    		<Compile TargetFile="{$Output}" IntermediateDirectory="{$IntermediateDirectory}"  CleanIntermediate="false" />
    	</Tasks>
    </Project>

    This psproj file is used by postsharp to extend it's searchpath. This means that on machines that are building the solution, you will need to supply some path where PostSharp can find the just mentioned psplugin file.

    Please note: there are other ways to configure the searchpath and possibly better ways to setup a system like this. There is a default searchpath and you could also put your plugin file there.

    The weaver factory
        public class PocoEDMAttributesWeaverFactory : Task, ILaosAspectWeaverFactory
        {

            #region ILaosAspectWeaverFactory Members
            /// <summary>
            /// creates the weaver
            /// </summary>
            /// <param name="aspect">the EDMAttributesSubAspect that instantiated this factory</param>
            /// <returns>the weaver that will do the lowlever hardcore work</returns>
            public LaosAspectWeaver CreateAspectWeaver(PostSharp.Laos.ILaosAspect aspect)
            {
                if (aspect is EDMAttributesSubAspect)
                {
                    EDMAttributesSubAspect edmAttributesAspect = (EDMAttributesSubAspect)aspect;
                    return new PocoEDMAttributesWeaver(edmAttributesAspect.EDMContainerName);
                }

                return null;
            }

            #endregion
        }

    Nothing special there. Using a factory allows you to supply different weavers for different aspects.

    So, to recap: we attached a plugin that did not do much itself. We used the assemblyinfo to tell PostSharp it should always use a certain task when compiling assemblies that are referencing our attribute assembly. We used the psproj file to make PostSharp search in the right spot and we used a psplugin file to tell map the task name to an actual factory.
    The factory creates our weaver, and we will discuss that in the next post!

  • Friday, February 22, 2008 10:41:17 AM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback