Monday, February 18, 2008

In this post I'd like to introduce version 0.1 of the first Entity Framework contribution project: Automatically implement the IPoco interfaces.
The project is aimed at helping you build your domain layer in a more persistence ignorant way, than is possible at this moment.

[official codeplex location of the project is here]

The full table of contents:

The Problem: baseclass needed

Microsoft is on the brink of releasing the Entity Framework. It is at beta 3 at this moment. If you are reading this blog, you are probably familiar with it, but let's do a quick summary:
The Entity Framework is a framework that maps between a database and your domain objects. It's grand vision is to easily allow you to (with a funky design-experience) create (multiple) conceptual models that know how to talk to the database. Although more than an OR-mapper, most people like to position it as such anyway.
EF is an abstraction layer on top of your datastore and will allow you to work with business objects that actually make sense from an object-oriented perspective, instead of making you work with datarows, tables and sets.

One part of the criticism that the Entity Framework gets at this moment, is the lack of persistence ignorance. This means that, when you use the Entity Framework, you will have to create business entities that are aware of the Entity Framework (they need to derive from a Entity Framework baseclass).
This goes against too many principles to mention, and the ADO.Net team have gotten quite a bit of comments about it (other more mature frameworks, like nHibernate do not force you into this). Rightfully so!
In the end, Daniel Simmons blogged about the criticism here: Persistence Ignorance: OK, I think I get it now.

The suggested Solution: implement interfaces

In order to take away the need to implement a base-class, the EF-team created a few interfaces that need to be implemented. That is as far as they can go in the first release.

So, you can implement 3 interfaces on your business objects, and no baseclass is needed. 
Although much better, I feel I should not have to spend time on, or burden my domain layer with, code to facilitate data access. My domain layer should be able to focus on one thing: solving the business problems of the client.
By introducing other code to my domain layer, developers will be distracted.

Bill McCafferty posts about DDD (Domain Driven Design) and EF here. He concludes:

In short, and at the risk of being laconic, I feel that the ADO.NET Entity Framework does for data communications what the ASP.NET page life cycle did for the presentation layer.  In trying to introduce simplification and increased productivity, it's actually going to result in higher complexity and decreased maintainability in the long run.  I appreciate what Microsoft is trying to do, and absolutely love some of their other ideas, but, for now, I'm going to pass on the ADO.NET Entity Framework.

Billy McCafferty

He is quite right!!

EF-Contrib: Easing the implementation of these interfaces

The 3 interfaces we are talking about are:

  • IEntityWithChangeTracker
  • IEntityWithKey
  • IEntityWithRelationships

Implementing these interfaces is sometimes called "IPoco": Poco stands for Plain Old C# (or Code) Object, and the I in IPoco means that you can still use your Poco object but have to implement these interfaces. (so, not Poco at all... but still!)

The current checked in project (find it here) uses Postsharp to actually change the IL-code of your assembly and implements these interfaces. That means that you can build a domain layer with a class like this:

    [Poco("ConnectionName")]
    public class Person
    {
        public int PersonID { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
    }

After compilation, the class will actually look a bit different on disk:

    public class Person : IEntityWithChangeTracker, IEntityWithKey, IEntityWithRelationships
    {
...
    }

So you can use this Person class, like you would use the classes that EF generates.

It is important to understand that there will be very little runtime performance costs involved. The code transformation is done at compile-time, once. At runtime, there is no magic AOP or whatever involved.

This approach is used by several other OR-Mappers and is very common in the Java world.

Is this Persistence Ignorance?

Obviously, it's not. Hopefully, in version 2.0 of the Entity Framework, full ignorance is achieved. However, if you want to use EF at your datalayer today, this approach will let you focus on the important stuff, instead of data access code.

Imagine changing your conceptual model. When implementing IPoco yourself, you will have to take care to change all kinds of attributes on top of your properties. This will quickly become a burden.

How does it work?
  • You will need to download and install Postsharp on all the machines that will build your application (developer machines and teambuild machine(s)).
  • Your domain layer will have to reference the EntityFrameworkContrib.PostSharp4EF assembly, and the PostSharp.Laos and PostSharp.Public assemblies. By referencing these, Postsharp will know to do a post-compilation phase on your assemblies.
  • You will need to supply a 'psproj' file in your assembly, to let our attribute know where it should look to actually do the implementation. This allows me to seperate the implementation assembly from what you need at runtime!
  • You have already created your edmx file, which EF will dissect into the individual .csdl, .msl and .ssdl files and place them in your bin/debug folder.
  • The project for now assumes a connection string to be present in your app.config
  • You can create your own simple business object.
  • That connection string is needed during the postcompilation phase to get to the individual mapping files, so use the attribute [Poco("")] to let us know you need to change this class.
  • The interfaces are implemented and the setters of your properties are modified to actually do changetracking
  • Actually, at this moment: INotifyPropertyChanged is implemented as well (let me know if you actually want this).

So, let's first look at the psproj file you need. In the Test-project, there is one already:

<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>

The referenced assembly EntityFrameworkContrib.PostSharp4EF only defines the Poco attribute, but does not contain the actually 'code-weaving'. If we would have placed the code-weaving in the same assembly as the Poco-attribute, you would have a much larger assembly to reference and you could get into licensing problems. By separating them, you only need to reference a tiny assembly.

The weaving assembly should not be distributed with your final product!

However, during the build, PostSharp does need to find the weaving assembly. Therefor, you need to create a psproj file that extends it's normal searchpath to also include the weaving dll.
Take care in naming the file: it should be named "projectname.psproj".

When the project is more mature, you might find it best to actually just place the weaving assembly into one of the default searchpaths for postsharp to find, and you will not need this psproj file.

Now, let's look at our attribute:
In it's constructor, it takes the name of the EDMcontainer, which should match your connection string. I have also added a few properties: Name, NamespaceName, PathToConfigFile. I'll get back to these in a later post. In the future, others will be added.

During the weaving, I have to do quite a bit of work to actually get to the correct mapping files. So, I try to load in your app.config and extract the file path's from it. The Testproject has the following app.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="OneSimpleTypeConnection" connectionString="metadata=.\bin\debug\OneSimpleType\OneSimpleType.csdl|.\bin\debug\OneSimpleType\OneSimpleType.ssdl|.\bin\debug\OneSimpleType\OneSimpleType.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=VISTAX64\SQLEXPRESS;Initial Catalog=EntityFrameworkTest;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

So, after loading that app.config, I use the supplied ConnectionContainer to get that connectionstring, and then use some simple regex work to get the path's to the mapping files. Then I try to load these to create a MetadataWorkspace.

When I finally have a MetadataWorkspace, stuff get's easier: I can iterate the properties in our original class and find the property in the metadataworkspace. Then I create the correct EDMScalar Attributes on top of those.

Implementing the interfaces is done by PostSharp, where it will look at an interface and just use a class I provide to call when one of the interface methods is called.

The result

Let's look through reflector at how the end result looks like. I won't show the methods, to keep things short and sweet.

  1 [EdmEntityType(Name="Person", NamespaceName="EntityFrameworkContrib.PostSharp4EF.Tests.OneSimpleType")]
  2 public class Person : INotifyPropertyChanged, IComposed<INotifyPropertyChanged>, IProtectedInterface<IFirePropertyChanged>, IPocoFacade, IComposed<IPocoFacade>
  3 {
  4     // Fields
  5     private IPocoFacade ~EntityFrameworkContrib.PostSharp4EF.IPocoFacade;
  6     private readonly InstanceCredentials ~instanceCredentials;
  7     private INotifyPropertyChanged ~System.ComponentModel.INotifyPropertyChanged;
  8     [CompilerGenerated]
  9     private string <Firstname>k__BackingField;
10     [CompilerGenerated]
11     private string <Lastname>k__BackingField;
12     [CompilerGenerated]
13     private int <PersonID>k__BackingField;
14
15     // Methods
16     static Person();
17     public Person();
18     void INotifyPropertyChanged.add_PropertyChanged(PropertyChangedEventHandler value);
19     EntityKey IEntityWithKey.get_EntityKey();
20     RelationshipManager IEntityWithRelationships.get_RelationshipManager();
21     void INotifyPropertyChanged.remove_PropertyChanged(PropertyChangedEventHandler value);
22     void IEntityWithKey.set_EntityKey(EntityKey value);
23     void IEntityWithChangeTracker.SetChangeTracker(IEntityChangeTracker changeTracker);
24     protected InstanceCredentials GetInstanceCredentials();
25     [DebuggerNonUserCode]
26     IPocoFacade IComposed<IPocoFacade>.GetImplementation(InstanceCredentials credentials);
27     [DebuggerNonUserCode]
28     INotifyPropertyChanged IComposed<INotifyPropertyChanged>.GetImplementation(InstanceCredentials credentials);
29     [DebuggerNonUserCode]
30     IFirePropertyChanged IProtectedInterface<IFirePropertyChanged>.GetInterface(InstanceCredentials credentials);
31
32     // Properties
33     [EdmScalarProperty(IsNullable=true)]
34     public string Firstname { [CompilerGenerated] get; [CompilerGenerated] set; }
35     [EdmScalarProperty(IsNullable=false)]
36     public string Lastname { [CompilerGenerated] get; [CompilerGenerated] set; }
37     [EdmScalarProperty(IsNullable=false, EntityKeyProperty=true)]
38     public int PersonID { [CompilerGenerated] get; [CompilerGenerated] set; }
39 }
40
41

Line 1 implements the needed EntityType attribute for EDM to work.
Line 2 shows that INotifyPropertyChanged and IPocoFacade is implemented. The facade interface just hides the 3 IPoco interfaces, so that's them! PostSharps adds IComposed interfaces as well.
Line 26 shows a call to the GetImplementation method of that interface. This way, a class I have added is returned where the actual work of the interface is done.
Line 33, 35 and 38 show the EDMScalarProperties being set.

What it does not do at this moment

I do not set default values for fields and I haven't spend any time on complex types and relations.

I first want to gauge community interest before spending more time on this project. So let me know if you would use this approach if it would be complete. I'm quite sure these things aren't too hard to accomplish, but they will take some time.

The Future

I'd like the EntityFramework Contrib project to provide easy tools to use EF in an enterprise system. I'm mostly interested in client/server SOA solutions. Other projects that might help in that aspect:

  • A custom changetracker that can be used on the client. This way the client will not have to reference Entity Framework at all.
  • Better serialization possibilities. Note that I do not automatically place datacontract attributes on top of the properties. I think it was a mistake for the ADO.Net team to implement their codegen to do this. (although I understand why).
    When I serialize a EF entity at this moment, I see all kinds of references to EF in the xml. I do not like that, and would like a beautiful clean xml representation of my business objects. (I don't want to be forced to use DTO's.).
  • Serializing original values. I can see a representation of the value with a xml attribute that shows what the original value was.

 

Feel free to contact me, or leave a comment here or at the projects home to let me know if you are interested!

kick it on DotNetKicks.com

Monday, February 18, 2008 2:50:21 PM (Romance Standard Time, UTC+01:00)  #    Comments [4]  |  Trackback

In this post and a few upcoming posts, I would like to present a solution I have built using Workflow as the controller for your WPF applications. I wish I could call it a framework and think of a great name for it, but it does not aim to solve all your UI-building problems in one go. It does however offer a very easy way to build a loosely coupled application, driven by WF and could be used to build upon for your own solution.

Table of contents

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

Inspiration

Like I mentioned in a blog post here, Josh Smith writes about using MVC in a WPF application where he does not use a funky IOC-container to help him build a MVC architecture, but uses the WPF framework itself to accomplish most of it.
This resonated with me, because I just left a project where the combination of WPF and CAB did not make good on all it's promises. The team sometimes felt the combination was overly complex.

Also Jeremy Miller writes about implementing all of the different aspects of CAB yourself. While doing so, he reasons (my interpretation) that it's best to build the simplest solution that is a precise fit for your problem, instead of using all kinds of big-time frameworks that abstract away so much, that you start to feel constrained.

A great little post by Rob Teixeira concludes that most frameworks are way too complex to really use.

I have had a bit of experience using WF on the server side, but have always thought of WF to be an excellent fit for the UI as well. When building complex UI's I would like nothing better than to be able to invite a business analyst to sit next to me and just show him what will happen when a button is pushed.
I have had a team build a large UI for a LOB application. Although at first glance it looked very simple, there is always going on much more than you expect. Having a visual representation of the flow of actions in your program, is a good thing.

This project aims to provide the most straight forward easiest plumbing possible, to get the job done. It tries to be explicit and make it easy for you (the developer) to do the right thing. It hopes that the use of WF provides some sort of DSL-feel to your application.

So, what does this mean

First, what does the solution not do:

  • It is explicitly not an IOC based solution (but perhaps you don't need that)
  • It is not a complete eventing mechanism (although controllers are able to communicate just fine)
  • It is not a finished solution (I might have called it a framework then!)

What it is, is this:

  • It is a suggestion for how you could very easily use workflows as a controller
  • It combines some fun tricks I've learned, that will facilitate us here
  • It uses the native power of WPF, so no learning of new concepts just because you have a ShinyNewFramework, if you understand WPF, you understand how to hook things up
  • It uses the native power of WF to create your controller logic, this translates into a very descriptive usecase with easy handoff between developers and opens up possibilities of just letting your business analysts create the first draft themselves! WF always feels like a cheap-ass DSL to me.
  • It is one adapter class, a couple of activities and a command service. Very easy to understand and adjust to fit your own needs
  • It facilitates loose coupling to the extend where your views and your controllers do not need references to eachother
  • It is message based
  • Excellent testability, because of loose coupling and messages.

 

Show us the goods

I have uploaded the goods zipped here.
It needs .net framework 3.5.

In the previous post, I explained how you could combine the controller and wpf in one project. It seems that this does not work as well as it should: sometimes I get build errors that aren't there. It's fine to have logic and views separate for the real sample, but the shell consists of two projects now as well, that may seem as a bit overkill.

I only UnitTested one small view to show how you can go about testing bindings and test the controller separately. I use TypeMock for this, so you might need to unload that project. (I'm considering TypeMock, but it is pretty expensive for a one-man-shop).

What's in it

The real stuff is very small.

  • project ControllersAdapters, with only one file. It is a contentcontrol, which acts as an adapter to your controllers [8 kb dll]
  • project WorkflowCommunications, which has the service that we can use to translate in/out of the controller and 6 custom activities, that do specific things [27 kb dll]

That is all you need.
I have loosely implemented the BankTeller application from CAB, or rather the SmartClientContrib 1.1 WPF for CAB. I did not look too closely at their implementation details, just copied the xaml and the domain model and build a part of it myself. Just to discover what was needed to build a real application.

image

The sample consists of a Shell, Domain, Logic, Views and Test project. It demonstrates how one could go about building such an application. I will follow up with a more detailed look at it. Suffice it to say, implementing it was a breeze.

The thing with the BankTeller application is, that the logic is too simple. So it mostly demonstrates hooking up views and datacontexts.

Just to give you a quick glance at what logic in a workflow looks like:

image

(Here you see what will happen when a new customer is selected in the listview. It checks if the customer is not null, and then sets a customerinfo view and a customer summary view. If it was null, the views are removed from the visual tree.)

 

Go into more detail, please

Well, I will follow up with more posts, if there is an interest in it. This post has dragged on long enough, so I will keep it very short for now.

The concepts are:

  1. Use WPF resources as an excellent container for objects. Resource lookups work hierarchically, so it's actually pretty powerful on it's own. There are two activities Inject- and RetrieveObjectFromResource that will put or retrieve an arbitrary object into the resource section of the adapter. This could be a service or something else.
  2. Use WF as an event aggregator. All workflows are registered to the runtime, and all adapters subscribe (with weakevents) to the workflow. So it's easy to send messages around.
  3. Use WPF Commands to communicate from the View to the Controller. Commands go upstream. I have made it easy for a controller to handle a command (just drag a HandleCommand to the screen). I've also made it possible to use rules to determine if the command 'CanExecute'. So you could do a command 'AcceptCustomer' and bind it to a button. The Controller will determine if the command can be executed. (When the customerqueue is empty in the sample, the button to accept a customer is disabled automatically).
  4. Use WPF DataTemplates to inject UI by the Controller. The View can sprinkle ContentPresenters around (with ContentTemplates bound to DynamicResources). The controller will choose what piece of UI to inject as the resource. (cool stuff!)

The most important class is the GenericWorkflowAdapter that can be placed into the UI like this:

<c:GenericWorkflowAdapter WorkflowController="{x:Type l:ShellLogic}" />

Here we tell it to use the workflowcontroller: ShellLogic as it's 'boss'.
The adapter will hook into the RoutedUI commands coming from WPF and when a command comes that the workflow wants to react to, it will send it to the workflow. The workflow will react to it.

Than, there is the CommandService, which defines the communication between the workflow and the runtime. The adapters use it to send messages to their workflow. The workflow uses it to communicate to the adapters.

There are custom activities to do specific UI-things. Like setting a controller in the UI, or an object in the resources. Setting the datacontext of a view with your ViewModel and actually setting the Content of the adapter with it's View.

More details will follow.

Trixxxxxx

In order to pull this off, a few things were hacked:

  • I created a much easier way to register commands on a workflow. Just drag a HandleCommand to an Eventdriven activity, set it's CommandName (the string it will react to) and you're off. Normal WF paradigm says you have to create an interface and possibly even implement correlation. Not productive for what we are trying to achieve.
  • Getting the workflow to communicate back to the adapter causes a clone to be made of the message. But since we don't want that, I implement IClonable to return 'this'. Works well, but you have been warned.
  • At one point I use a delegate that is passed to the workflow, that let's it get data from the commandService on the fly.
  • In order to use the custom activities, I needed to let the user (you) select types (what view you wish to inject, what controller you want to instantiate). I've had to jump through hoops to get it working. See this blog post.

What is next

I've had great fun implementing this. After a few refactorings, it turned out to be extremely simple. I'm interested in seeing what you think. If there is some interest from the community, it could easily be taken to the next level. However, at this point it was just a nice experiment for me. Let me know what you think of the idea!!

kick it on DotNetKicks.com

Monday, February 18, 2008 12:19:33 PM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Thursday, February 14, 2008

Just ran into a little bug in Visual Studio/msbuild and could not find any answers in the forums, so I thought I'd put it up here for reference:

When you want to use both workflow classes and wpf classes in one project, you will run into some strange behaviour. Let's do it together.
If you want to skip the newbie stuff, jump to step 11 and see the bug.

  1. create a WPF project.
  2. unload the project and choose to edit the project file
  3. somewhere in the beginning of the file, you will find the following line:
    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    That is a way for visual studio to identify this as a WPF application project, and when you add an item, you will be able to choose a wpf item.
  4. You wish to be able to compile WF items, so add to the bottom of the file the correct import for the WF tasks:
    <Import Project="$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.5\Workflow.Targets" />
  5. Note that WPF in the past needed the import of winfx, but with framework 3.5 you don't need that anymore!
  6. At this point you are able to copy a workflow or activity to your project and compile, but you want to be able to add WF items to your project, so scroll to the top of the file again.
  7. Add the Guid that identifies a WF project ({14822709-B5A1-4724-98CA-57A101D1B079};)  to your projecttypeguids tag. The complete tag should be on one line (!) and look like this:

    <ProjectTypeGuids>{14822709-B5A1-4724-98CA-57A101D1B079};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
  8. Save the file and reload the project.
  9. Before adding a the first workflow to the project, first add references to System.Workflow.Runtime, Activities and Componentmodel.
  10. Add your first glorious workflow to the project.
  11. Be prepared to be disappointed: the project will not compile. Mine gave this error:

    Error    1    Error reading resource file 'j:\Users\Ruurd\Documents\Visual Studio 2008\Projects\WF_and_WPF_combined\WpfApplication1\obj\Debug\WpfApplication1.obj.Debug.WpfApplication1.g.resources' -- 'The system cannot find the file specified. '    J:\Users\Ruurd\Documents\Visual Studio 2008\Projects\WF_and_WPF_combined\WpfApplication1
  12. Notice the weird path of the resource file. It is looking for something with dots instead of path dividers. Strange.
    In regular windows explorer, go to the obj/Debug folder, and create a copy of the .g.resources file and use that weird name. I wanted to automate it though, so go to the properties of your project and use this as your pre-build script:
    IF EXIST "$(ProjectDir)obj\$(ConfigurationName)\$(TargetName).g.resources" (copy /-Y "$(ProjectDir)obj\$(ConfigurationName)\$(TargetName).g.resources" "$(ProjectDir)obj\$(ConfigurationName)\$(TargetName).obj.$(ConfigurationName).$(TargetName).g.resources") ELSE (echo "placeholder" > "$(ProjectDir)obj\$(ConfigurationName)\$(TargetName).obj.$(ConfigurationName).$(TargetName).g.resources")

    This checks to see if you already have a g.resources file and if so, copies it. Otherwise it will generate a placeholder file with the correct name. Atleast the project will build without problems.

I have not tested it a lot yet. It seems to me that when the placeholder is created, there are resources that can not be found. During some quick and dirty tests, I've not had any problem yet and everything works just fine.

Hope this helps someone out there.

update: weird stuff. I have this running just fine in a couple of projects, but I have one project that gives an exception during a rebuild (not a build) in the compileworkflowtask. In other 'combined' projects, I can happily build and rebuild using the steps above.

This is probably caused by wpf renaming the file to tmp_proj and the compileworkflow task is validating it's parameters like so:

        if ((string.Compare(this.ProjectExtension, ".csproj", StringComparison.OrdinalIgnoreCase) != 0) && (string.Compare(this.ProjectExtension, ".vbproj", StringComparison.OrdinalIgnoreCase) != 0))
        {
            base.Log.LogErrorFromResources("UnsupportedProjectType", new object[0]);
            return false;
        }

The logging statement is the one giving the pain.

 

Thursday, February 14, 2008 1:44:34 PM (Romance Standard Time, UTC+01:00)  #    Comments [5]  |  Trackback
 Wednesday, February 13, 2008

I'm working on a sweet project at the moment using both WPF and WF. One of my custom activities has a property of type Type, where it would be cool for the user of the activity to be able to use the designer to select a type, just like what happens in the WF designer when I choose a type. However, no type picker popped up.

So I went googling and found that Daniel Cazzulino also ran into this problem and created a fantastic little project to harness the power of the real WF typebrowser. He writes about it on this blogpost and later moves the project to code project. You can find the article and his download code here.

However, as you can read in the comments, something was broken. Looking through the code, although small, made me not want to waste time on understanding the System.ComponentModel namespace in that much detail at this point ;-) (although, when working with WF, you will soon need to customize property pickers, so I will have to look into it someday soon).
Daniel himself points to the Patterns and Practises entlib library: they offer the same functionality. I downloaded their sourcecode, and I'm quite sure they just used Daniels code and improved upon it a bit. However, with all the Entlib references, the project felt a bit heavy.

What I have done is rip out all the references to entlib that I do not care about, used a few files from Daniels original solution and worked around a few shortcomings. Nothing fancy, I just hacked at it until it worked.

image

 

Now, since I have used some code (without license) by Daniel and code by the Entlib group, I'm not sure if I can publish a derivative without getting into problems. However, I've read their license, and I think it's okay.

You can download the project here, don't ask for changes because I'm not interested in spending more time on it. All credits go to Daniel.

(Also, find out how to create your own typefilters in his post).

Have fun with it. Leave a comment if you find it useful.

Wednesday, February 13, 2008 1:30:24 PM (Romance Standard Time, UTC+01:00)  #    Comments [7]  |  Trackback

Grigori Melnik just blogged about the release of the first CTP for the Unity Framework. It can be downloaded from codeplex here.

I think I mentioned Unity before. The Unity framework is build on top of ObjectBuilder2. ObjectBuilder2 seems a much better factory system than ObjectBuilder (infamous for it's bloated misuse in CAB). I have been following along with some sample on how to use ObjectBuilder2 and I quite like it. Obvious, nowhere near as powerful as Windsor, Spring.Net or StructureMap yet, but I understand Microsoft needs it's home-grown factory system, and ObjectBuilder2 seems easy enough to use.

The Unity framework uses ObjectBuilder2 to provide a IOC. It can be used like so:

UnityContainer container = new UnityContainer() 
                  .Register<ILogger, TraceLogger>() 
                  .Register<ISomething, Something>()
                  .Register<ISomethingElse, SomethingElse>();

container.Get<ISomething>();

I'll certainly be looking into it!

Wednesday, February 13, 2008 10:40:19 AM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Tuesday, February 12, 2008

It frequently happens that you wish to enrich a valuetype with more data, most often the properties in your domainmodel. In this post I will present one way you could achieve that. But first, let's look at why you would want such a thing, then look at how you would go about this normally and finally look at another approach.

Why metadata about a property

Let's say you have a domainobject 'Person' like so:

    public class Person
    {
        public string Name { get; set; }
        public DateTime Birthday { get; set; }
    }

When working with this object, you will set the property 'Name' and property 'Birthday', but while setting these, you have no clue about what really is allowed to go in there. Maybe Name can not accept numerics and in our domain, any Birthday before 1-1-1990 is not allowed. These validationrules are unknown until you actually validate the object, using your preferred mechanism. At that point, there might be an error collection that will state which properties are set to disallowed values. Maybe validation will occur on each change to the data.

That's not really a problem for your businesslogic, but your UI might want to know about these validation rules beforehand! Maybe it could adjust to show a different textbox for 'Name', one which will not let you enter a number, for instance.
Yes, sure you could have put that specialized textbox in there yourself, but that means you will have to adjust your UI views when businessrules change. I would much rather just place a generic control, bind it to my property and let it decide for itself how best to present the data:

<MetaDataEditor Content="{Binding Path=Name}" />  <!-- this shows an alphanumerical textbox -->

So, why metadata: it allows you to optimize beforehand and simplify your UI.

Freaky
Oh, or maybe you want to give a 'friendly name' to the property. That friendly name could be presented in the UI as the label or used in error messages.
How do you go about this normally

(and I say 'normally' not in a bad way, it might still be the best way, depending on your situation).

You would define some interface:

    interface IMetadataProvider
    {
        Metadata GiveMetadataForProperty(string propertyName);
    }

and implement that on Person. Now, when you want your metadata object, you just get to the object on which the property is defined, and ask for it. Easy.

Metadata<T>

What I do not like about an interface, is the fact that you have separated the metadata from the property itself. There now is a method in my domainobject that will take a string (ouch) and probably go through a long list of  'if(propertyName == "???")' or switch/case statements until it gets to the correct name and then create or return a metadata object. That's a great deal of hooking up you need to do, and when passing strings, your domainmodel just became less easy to refactor.
When my magical MetaDataEditor needs the metadata, it will have to somehow find it by traversing from the bound property to it's parent and cast that to IMetadataProvider.

Oh, bad boy, don't even think about using reflection to magically connect the passed string to a metadataobject!

That is why I am experimenting with a little class, I like to call Metadata<T>.

    public class MetaData<T>
    {
        public T InnerValue { get; set; }
        .... goodness inside
    }

This way, you need to define a property on your businessobject like so:

private MetaData<string> name = new MetaData<string>();

public MetaData<string> Name
{
    get
    {
        return name;
    }
    set
    {
        name.InnerValue = value.InnerValue; 
    }
}

This way, you can rest assured the original metadata object is never discarded, but only the innervalue is changed.

We could work with the property like so (p is an instance of Person):
p.Name = new MetaData<string>("foo");

That's not easy, but we can also say:
p.Name.InnerValue = "foo";

Better. We can do one better though, by creating a few implicit operators on the metadataobject:

public static implicit operator T(MetaData<T> source)
{
    return source.InnerValue;
}

public static implicit operator MetaData<T>(T source)
{
    IMetaData md = source as IMetaData;
    if (md != null)
    {
        IConvertible convertible = md.InnerValue as IConvertible;
        if (convertible != null)
        {
            T converted = (T)convertible.ToType(typeof(T), null);
            return new MetaData<T> { InnerValue = converted };
        }

        throw new NotSupportedException();

    }
    else
    {
        return new MetaData<T> { InnerValue = source };
    }
}

This means, we can now use the property as follows:

p.Name = "foo";

The string "foo" can be translated to a MetaData<T> and that is going into the property-setter. Then, the setter will take the innervalue of that foo-metadataobject and use it to set it's own innervalue.

string importantname = p.Name   will work too.

One important note though: this might be misleading to your developers. They can not do p.Name.ToCharArray(), because p.Name really is not a string.
Or p.Car.Color. You would have to do p.Car.InnerValue.Color.

Now, whether you go with the implicit operators or not, you want to ease databinding especially. For that, a typeconverter can be used.

A typeconverter can be attached to a class by the use of an attribute, like so: [TypeConverter( typeof(MetadataForDatabindingConverter))]

The converter needs to inherit from TypeConverter. Let's implement one.

  1 public class MetadataForDatabindingConverter : TypeConverter
  2 {
  3     /// <summary>
  4     /// keep the real type of the metadata innervalue. Since we need it when we convert back to our metadata
  5     /// object.
  6     /// </summary>
  7     private Type databindingRealType;
  8
  9     public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
10     {
11         if (sourceType.Equals(typeof(string)))
12             return true;
13         else
14             return false;
15     }
16
17     public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
18     {
19         if (destinationType.Equals(typeof(string)))
20             return true;
21         else
22             return false;
23     }
24
25     public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
26     {
27         // ugly but necessary: when databinding to a ui control, it's likely that you want to go to a string representation
28         // when the ui control (textbox?) was changed, the incoming value is a string. I have not yet found a way to
29         // find out what the target really wants (for instance an MD<int>).
30         // This hack works fine
31
32
33         Type realtype = value.GetType();
34         if (databindingRealType != null)
35             realtype = databindingRealType;
36
37 
39         // or just do a switch on the type and create the correct type
40         //if(value is string)
41         //    return (IMetaData) new MD<String> { InnerValue = (string)value };
42
43         // because I don't feel like implementing the above statements.. bla!
44         Type d1 = typeof(MetaData<>);
45         Type constructed = d1.MakeGenericType(new Type[] { realtype });
46         IMetaData instance = (IMetaData)Activator.CreateInstance(constructed);
47
48         TypeConverter converter = TypeDescriptor.GetConverter(realtype);
49         converter.ConvertFrom(context, culture, value);
50
51         instance.InnerValue = converter.ConvertFrom(context, culture, value);
52
53         return instance;
54     }
55
56     public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
57     {
58         // so, this is a metadata object, and we are going to be converting the innervalue to a string (for textboxes etc).
59
60         IMetaData md = value as IMetaData;
61         if (md != null)
62         {
63             databindingRealType = md.InnerType;
64
65             TypeConverter converter = TypeDescriptor.GetConverter(databindingRealType);
66             if (converter.CanConvertTo(destinationType))
67             {
68                 return converter.ConvertTo(context, culture, md.InnerValue, destinationType);
69             }
70         }
71
72         throw new NotSupportedException(String.Format("Conversion of {0} to type {1} is not possible.",value.ToString(), destinationType.Name.ToString() ) );
73     }
74
75     public MetadataForDatabindingConverter()
76     {
77
78     }
79
80 }
 

A typeconverter should override the CanConvertFrom/To methods to indicate if it is able to convert between certain types. Our UI will present data as strings (textbox), so I have opted to only convert to and from strings.

Line 7 keeps a variable where the 'real type' will be put. The databinding engine does not give much information during the call to convert. So if we have a MetaData<int> and bind that to a textbox, the ConvertFrom only gives us information about the value being set (the string "1234"). How do we know we have to convert to MetaData<int> instead of MetaData<string>?
Well, turns out we do know at an earlier conversion that always happens: converting our metadata to a string that will be put into the textbox. I cache the 'realtype' at that moment. (I'm not happy with that solution, if you know how to get rid of the obvious codesmell there, leave a comment!).

The ConvertTo method is easy enough to not have to describe here, but in the ConvertFrom, we do have to jump through some hoops. I've opted to create a metadata<T> with reflection, using the correct type for T. Then, convert the passed in string to the correct type.

This works brilliantly and it allows you to bind like this:

<TextBox Text="{Binding Path=Name}" />

(When it is time to navigate through a property, you will have to go through InnerValue again though, like {Binding Path=Car.InnerValue.Color} .)

Microsoft's latest approach: IDataErrorInfo

The WPF team has invented dependency properties as another way to do something similar (for different reasons though). You obviously do not want to use dependency properties in your domain model.

The recently introduced IDataErrorInfo has the following definition:

        #region IDataErrorInfo Members

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get { throw new NotImplementedException(); }
        }

        #endregion

I hate that.

Especially the name of the argument 'columnName'. Drives me mad. My business object is a person or a car, not a databasetable. F*ck off.

Besides, what if you want to do something useful with an index on your object? Madness, I tell you!

Conclusion

It's annoying that you have to go to the innervalue property to get to the real value you are interested in. Implicit operators make this a lot more transparent but possibly confusing. Besides, there is a tiny performance loss here.

However, you can do great stuff with such a setup. Let the metadataobjects implement INotifyPropertyChanged as well and use them in pipelines (more on this later), query validation rules from it without having to think about getting to the object that holds the property, and more.

What do you think?

Tuesday, February 12, 2008 8:08:58 PM (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
 Saturday, February 09, 2008
update 2: I also posted this on the forums and the team finally found what was causing this. They explain:

There have been several reports where intellisense has completely stopped working for all projects after installing a version of the Windows SDK or MSDN. We have been able to track down the source of this problem. This seems to only affect installs of the SDK/MSDN post the installation of Visual Studio. One registry value has been incorrectly reset after these installs causing this failure. This issue has been handed off to setup team for a future fix.

In the meantime, if you encounter this issue, it can be fixed using regedit. First, determine if you are seeing this same issue by opening regedit and looking at the key:

HKEY_CLASSES_ROOT\CLSID\{73B7DC00-F498-4ABD-AB79-D07AFD52F395}\InProcServer32

If (Default) is empty you are hitting this issue. To correct the problem, change the value of (Default) to point to the location of TextMgrP.dll on your system (C:\Program Files\Common Files\Microsoft Shared\MSEnv\TextMgrP.dll in my case with a C: OS drive and accepting all the defaults). Restart Visual Studio and intellisense should be working again. Thanks to everyone who submitted reports of this issue and gave us the additional details needed to track it down quickly.

Update: If you are running a 64-bit version of Windows, you will need to make sure you are running the correct regedit version (%systemroot%\syswow64\regedit - see http://support.microsoft.com/kb/305097) and you will need to locate the correct path to TextMgrP.dll (such as C:\Program Files (x86)\Common Files\Microsoft Shared\MSEnv\TextMgrP.dll)

 

Update: a repair of visual studio eventually fixed this. Lesson learned: a repair does not damage already installed hotfixes and addins, so you do not have to fear losing anything.

I lost my xaml intellisense and I really miss it. I installed SDK 6.1, but I do not know if that was the cause. I was using Resharper, so I didn't notice. However, when I uninstalled resharper, intellisense did not appear again! It could have been the sdk. It could have been resharper. Or something else all together. I just don't know.

Lot's of googling did not really help (2008 is different than 2005), but did point to the importance of two files in your xml/schemas folder:

- XamlPresentation2006.xsd
- xaml2006.xsd

However, VS 2008 does not work with xsd anymore to supply intellisense. I was under the impression that a Xaml-parser service was build. I do not have those files and on another computer (where intellisense works fine), I did not find them either.

I copied them from a vs2005 install, and opened a xaml file in the xml editor. No schemas were defined (nor are they on the healthy computer), but when I pointed to the just copied files, intellisense does work partially again. It does not see usercontrols and stuff. This is not the way it is supposed to work in 2008!

Funny thing though: I now have this intellisense in the xmleditor, but not in sourcecode editor or the designer. In the healthy install, it's the other way around.

Let me know if you have a solution!

Saturday, February 09, 2008 11:06:22 PM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback

Dax Pandhi, of Reuxables is offering a lite version of their commercial theme: paper. You only get the compiled dll, but still, it's a bargain ;-)

I have not used any commercial themes yet, and as I am not working for a client at this point, I probably won't at this moment ;-) I also do not know yet whether I like the theme. I am going to use it and just see!

Are there other commercial theme packs around? I would like a pack that makes my applications look like this application ;-)

Saturday, February 09, 2008 9:05:07 PM (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback

If you are working with clients that do not see the use of automated testing (be it in unit tests of code blocks, or specific UI testing), you are in for a hard time. Maybe you should walk away, but let's face it: you will probably give in and try to do your best.
I have even had heated discussions with developers that do not see the use of it, certainly when there are monkey-testers to do it.

Testing the userinterface is incredibly hard to do. When you're testers are brave, they might use a testtool (robot) that will simulate clicks and read out information. However, these scripts have to be updated when the software changes and that is costly.

WPF has great support for UI Automation, which allows other programs to interact with your application's UI from the outside. It does this by naming the elements of your UI and offers 'strategies' to interact with them (Press this button).
It's not an easy framework, but workable.

Project White seems to be an abstract layer on top of the UI Automation stack, released to the public domain by ThoughtWorks today. It's aimed at simplifying your scripts and presenting a uniform API for both Winform and WPF technologies.

I'm looking forward to discovering it's api. This looks nice:

 

Application application = Application.Launch("foo.exe");
   Window window = application.GetWindow("bar", InitializeOption.NoCache);
Button button = window.Get<Button>("save");
button.Click();

Do you use UI automation to test your application?

Saturday, February 09, 2008 8:54:33 PM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback