Monday, December 8, 2008

Hire the funny guy

I have seen several posts about this topic, among them one from Joel Spolsky Exploding Offer Season and his article on Inc.com from a while back. And there are the re-occurring posts where bloggers ask their readers if anybody would be interested in coming to work for them. I started to think a little bit what good qualities you want in a Developer.

And I say hire the funny guy, and I don’t mean the guy that can tell 100k different jokes, I mean the guy that reacts to his environment in a funny / smart way. It takes creativity, knowledge, people skills and the ability to quickly find an answer to a problem, the basic skills you would want in a developer. So when you have a choice between two equally qualified developers, choose the funny one, besides the already mentioned benefits it is also very pleasant to work with them :)

-Mark

Saturday, November 29, 2008

Linq is Cool, but…

Linq is great, got to love its ability to query object structures. In the following examples that I’ll show you I am only touching the abilities of Linq. And as you can see it is capable of doing some really cool things, but it comes at a price…

But first here is the basic object structure I use in the example:

Multiple classes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
using System.Collections.Generic;

namespace LinqIsCool
{
    public class DataStructure
    {
        public readonly Dictionary<string, Author> Authors;
        public readonly List<Blog> Blogs;
        public readonly Dictionary<string, Post> Posts;

        public DataStructure()
        {
            Authors = new Dictionary<string, Author>
            {
                {"mark",   new Author("Mark Nijhof")},
                {"mona",   new Author("Mona Nijhof")},
                {"milo",   new Author("Milo Nijhof")},
                {"thalia", new Author("Thalia Nijhof")}
            };
            Posts = new Dictionary<string, Post>
            {
                {"post0", new Post("Tech talk 1",   Authors["mark"])},
                {"post1", new Post("Tech talk 2",   Authors["mark"])},
                {"post2", new Post("Tech talk 3",   Authors["mark"])},
                {"post3", new Post("Family talk 1", Authors["mona"])},
                {"post4", new Post("Tech talk 4",   Authors["mark"])},
                {"post5", new Post("Family talk 2", Authors["mona"])},
                {"post6", new Post("Tech talk 5",   Authors["mark"])},
                {"post7", new Post("Tech talk 6",   Authors["mark"])},
                {"post8", new Post("Family talk 2", Authors["mark"])},
                {"post9", new Post("Family talk 3", Authors["milo"])}
            };

            Blogs = new List<Blog>
            {
                new Blog("Blog.Fohjin.com", Authors["mark"]) 
                { 
                    Posts = new List<Post>
                    {
                        Posts["post0"],
                        Posts["post1"],
                        Posts["post2"],
                        Posts["post4"],
                        Posts["post6"],
                        Posts["post7"],
                        Posts["post8"]
                    }
                },
                new Blog("KidsTalk.Nijhof.com", Authors["mark"]) 
                { 
                    Posts = new List<Post>
                    {
                        Posts["post9"]
                    }
                },
                new Blog("Family.Nijhof.com", Authors["mona"])
                { 
                    Posts = new List<Post>
                    {
                        Posts["post3"],
                        Posts["post5"],
                        Posts["post8"],
                        Posts["post9"]
                    }
                }
            };
        }
    }

    public class Author
    {
        public string AuthorName { get; set; }
        public Author(string name)
        {
            AuthorName = name;
        }
    }

    public class Blog
    {
        public string BlogName { get; set; }
        public Author Owner { get; set; }
        public IList<Post> Posts { get; set; }
        public Blog(string name, Author owner)
        {
            BlogName = name;
            Owner = owner;
        }
    }

    public class Post
    {
        public string Title { get; set; }
        public Author Author { get; set; }
        public Post(string title, Author author)
        {
            Title = title;
            Author = author;
        }
    }
}


Wow that was long. Now the code below will actually show you several examples of using Linq, look at the comments for an explanation:

class LinqExamples
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
using System;
using System.Collections.Generic;
using System.Linq;

namespace LinqIsCool
{
    public class LinqExamples
    {
        private readonly DataStructure dataStructure;

        public LinqExamples()
        {
            dataStructure = new DataStructure();
        }

        /// <summary>
        /// Parses the data structure to find Authors that do not own a Blog
        /// How does it work:
        /// The Linq query is joining all the available Authors with the Blogs connecting 
        /// the Author with the Blog.Owner place the results in blogAuthors. The
        /// DefaultIfEmpty operator supplies a default element for an empty sequence,
        /// which in our example means that if there is no matching Blog for an Author it
        /// will return null. Then we specify to only select the objects where blogAuthor
        /// is null, so in effect only selecing Authors that have no Blog
        /// </summary>
        public void GetAuthorsThatDoNotOwnABlog()
        {
            var authors = 
            (
                from author in dataStructure.Authors.Values
                join blog in dataStructure.Blogs on author equals blog.Owner into blogAuthors
                    from blogAuthor in blogAuthors.DefaultIfEmpty()
                    where blogAuthor == null
                select author
            ).ToList();

            authors.ForEach(x => Console.WriteLine("- " + x.AuthorName));
        }

        /// <summary>
        /// Parses the data structure to find the number of Blogs an Authors owns
        /// How does it work:
        /// Selects every Author from the dataStructure.Authors.Values list and adds a Blogs
        /// List that gets its content from a sub Ling Query that basically selects all the 
        /// Blogs from the current Author and returns the Count for it
        /// </summary>
        public void GetNumberOfBlogsPerAuthor()
        {
            var authors = 
            (
                from author in dataStructure.Authors.Values
                select new
                {
                    _Autor = author,
                    _Blogs = 
                    (
                        from blog in dataStructure.Blogs
                        where blog.Owner == author
                        select blog
                    ).ToList().Count()
                }
            ).ToList();

            authors.ForEach(x => Console.WriteLine("- " + x._Autor.AuthorName + " owns " + x._Blogs + " blogs"));
        }

        /// <summary>
        /// Parses the data structure to find the actual Blogs an Authors owns
        /// How does it work:
        /// Selects every Author from the dataStructure.Authors.Values list and adds a Blogs
        /// List that gets its content from a sub Ling Query that basically selects all the 
        /// Blogs from the current Author and returns the List
        /// </summary>
        public void GetBlogsPerAuthor()
        {
            var authors = 
            (
                from author in dataStructure.Authors.Values
                select new
                {
                    _Autor = author,
                    _Blogs = 
                    (
                        from blog in dataStructure.Blogs
                        where blog.Owner == author
                        select blog
                    ).ToList()
                }
            ).ToList();

            authors.ForEach(x =>
            {
                Console.Write("- " + x._Autor.AuthorName + " owns ");
                x._Blogs.ForEach(y => Console.Write(y.BlogName + " "));
                Console.WriteLine();
            });
        }

        /// <summary>
        /// Parses the data structure to find specific Posts that belong to a specific Blog
        /// How does it work:
        /// First the Linq query specifies that it will use both dataStructure.Posts and
        /// dataStructure.Blogs. Then it specifies that the Blog should be the same as
        /// selectedBlog, the next line specifies that the resulting Posts should be part of 
        /// the selected Blog.Posts list and the final step is to specify that the resulting 
        /// Posts should be part of the provided list requestedPostIds. Then it selects the Post
        /// </summary>
        public void GetSpecificPostsFromSpecificBlog()
        {
            var requestedPostIds = new List<string> {"post0", "post1", "post9"};
            var selectedBlog = dataStructure.Blogs[0];

            var selectedPosts = 
            (
                from post in dataStructure.Posts
                from blog in dataStructure.Blogs
                where
                    blog == selectedBlog
                    && blog.Posts.Contains(post.Value)
                    && requestedPostIds.Contains(post.Key)
                select post.Value
            ).ToList();

            selectedPosts.ForEach(x => Console.WriteLine("- " + x.Title + " by " + x.Author.AuthorName));
        }

        /// <summary>
        /// Parses the data structure to find Posts from a specifies Author on a Blog where the Author is not the Owner
        /// How does it work:
        /// First the Linq query specifies that it will use both dataStructure.Posts and
        /// dataStructure.Blogs. Then it specifies that the Post should be the same as
        /// requestedAuthor, the next line specifies that the blog.Owner should not be part of 
        /// the same as requestedAuthor and the final step is to specify that the resulting 
        /// Posts should be part of the Posts list of the current Blog. Then is selects the 
        /// Post and the Blog
        /// </summary>
        public void GetPostsFromSpecificAuthorWhereNotBlogOwner()
        {
            var requestedAuthor = dataStructure.Authors["mark"];

            var selectedPosts = 
            (
                from post in dataStructure.Posts
                from blog in dataStructure.Blogs
                where
                    post.Value.Author == requestedAuthor
                    && blog.Owner != requestedAuthor
                    && blog.Posts.Contains(post.Value)
                select new
                {
                    post.Value, 
                    blog
                }
            ).ToList();

            selectedPosts.ForEach(x => 
                Console.WriteLine("- " + 
                    x.Value.Title + " by " + 
                    x.Value.Author.AuthorName + " on " + 
                    x.blog.BlogName));
        }
    }
}


Now we finally get to the part where we talk about the downside of Linq queries, you really quickly run into the risk that your code becomes unreadable. So when you do write some complex Linq queries I would suggest you also write proper comments use understandable variable names and perhaps split the Linq query into multiple Linq queries. Below here is the output when running the methods:

GetAuthorsThatDoNotOwnABlog()
- Milo Nijhof
- Thalia Nijhof

GetNumberOfBlogsPerAuthor()
- Mark Nijhof owns 2 blogs
- Mona Nijhof owns 1 blogs
- Milo Nijhof owns 0 blogs
- Thalia Nijhof owns 0 blogs

GetBlogsPerAuthor()
- Mark Nijhof owns Blog.Fohjin.com KidsTalk.Nijhof.com
- Mona Nijhof owns Family.Nijhof.com
- Milo Nijhof owns
- Thalia Nijhof owns

GetSpecificPostsFromSpecificBlog()
- Tech talk 1 by Mark Nijhof
- Tech talk 2 by Mark Nijhof

GetPostsFromSpecificAuthorWhereNotBlogOwner()
- Family talk 2 by Mark Nijhof on Family.Nijhof.com


Just for fun I “Alt + Enter”-ed a couple times, did some manual formatting and viola you have the same results but now using Lambda, remember I said something about readability?

class LambdaExamples
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
using System;
using System.Collections.Generic;
using System.Linq;

namespace LinqIsCool
{
    public class LambdaExamples
    {
        private readonly DataStructure dataStructure;

        public LambdaExamples()
        {
            dataStructure = new DataStructure();
        }

        /// <summary>
        /// Parses the data structure to find Authors that do not own a Blog
        /// How does it work:
        /// The Linq query is joining all the available Authors with the Blogs connecting 
        /// the Author with the Blog.Owner place the results in blogAuthors. The
        /// DefaultIfEmpty operator supplies a default element for an empty sequence,
        /// which in our example means that if there is no matching Blog for an Author it
        /// will return null. Then we specify to only select the objects where blogAuthor
        /// is null, so in effect only selecing Authors that have no Blog
        /// </summary>
        public void GetAuthorsThatDoNotOwnABlog()
        {
            var authors = 
            (
                dataStructure.Authors.Values.GroupJoin(
                    dataStructure.Blogs, 
                    author => author, 
                    blog => blog.Owner,
                    (author, blogAuthors) => new {author, blogAuthors}
                ).SelectMany(
                    @t => @t.blogAuthors.DefaultIfEmpty(), 
                    (@t, blogAuthor) => new {@t, blogAuthor}
                ).Where(
                    @t => @t.blogAuthor == null
                ).Select(
                    @t => @t.@t.author
                )
            ).ToList();

            authors.ForEach(x => Console.WriteLine("- " + x.AuthorName));
        }

        /// <summary>
        /// Parses the data structure to find the number of Blogs an Authors owns
        /// How does it work:
        /// Selects every Author from the dataStructure.Authors.Values list and adds a Blogs
        /// List that gets its content from a sub Ling Query that basically selects all the 
        /// Blogs from the current Author and returns the Count for it
        /// </summary>
        public void GetNumberOfBlogsPerAuthor()
        {
            var authors = 
            (
                dataStructure.Authors.Values.Select(
                    author => new 
                    { 
                        _Autor = author, 
                        _Blogs =
                        (
                            dataStructure.Blogs.Where(
                                blog => blog.Owner == author
                            )
                        ).ToList().Count()
                    })
            ).ToList();

            authors.ForEach(x => Console.WriteLine("- " + x._Autor.AuthorName + " owns " + x._Blogs + " blogs"));
        }

        /// <summary>
        /// Parses the data structure to find the actual Blogs an Authors owns
        /// How does it work:
        /// Selects every Author from the dataStructure.Authors.Values list and adds a Blogs
        /// List that gets its content from a sub Ling Query that basically selects all the 
        /// Blogs from the current Author and returns the List
        /// </summary>
        public void GetBlogsPerAuthor()
        {
            var authors = 
            (
                dataStructure.Authors.Values.Select(
                    author => new
                    {
                        _Autor = author,
                        _Blogs =
                        (
                            dataStructure.Blogs.Where(
                                blog => blog.Owner == author
                            )
                        ).ToList()
                    }
                )
            ).ToList();

            authors.ForEach(x =>
            {
                Console.Write("- " + x._Autor.AuthorName + " owns ");
                x._Blogs.ForEach(y => Console.Write(y.BlogName + " "));
                Console.WriteLine();
            });
        }

        /// <summary>
        /// Parses the data structure to find specific Posts that belong to a specific Blog
        /// How does it work:
        /// First the Linq query specifies that it will use both dataStructure.Posts and
        /// dataStructure.Blogs. Then it specifies that the Blog should be the same as
        /// selectedBlog, the next line specifies that the resulting Posts should be part of 
        /// the selected Blog.Posts list and the final step is to specify that the resulting 
        /// Posts should be part of the provided list requestedPostIds. Then it selects the Post
        /// </summary>
        public void GetSpecificPostsFromSpecificBlog()
        {
            var requestedPostIds = new List<string> {"post0", "post1", "post9"};
            var selectedBlog = dataStructure.Blogs[0];

            var selectedPosts = 
            (
                dataStructure.Posts.SelectMany(
                    post => dataStructure.Blogs, 
                    (post, blog) => new {post, blog}
                ).Where(
                    @t => @t.blog == selectedBlog
                          && @t.blog.Posts.Contains(@t.post.Value)
                          && requestedPostIds.Contains(@t.post.Key)
                ).Select(
                    @t => @t.post.Value
                )
            ).ToList();

            selectedPosts.ForEach(x => Console.WriteLine("- " + x.Title + " by " + x.Author.AuthorName));
        }

        /// <summary>
        /// Parses the data structure to find Posts from a specifies Author on a Blog where the Author is not the Owner
        /// How does it work:
        /// First the Linq query specifies that it will use both dataStructure.Posts and
        /// dataStructure.Blogs. Then it specifies that the Post should be the same as
        /// requestedAuthor, the next line specifies that the blog.Owner should not be part of 
        /// the same as requestedAuthor and the final step is to specify that the resulting 
        /// Posts should be part of the Posts list of the current Blog. Then is selects the 
        /// Post and the Blog
        /// </summary>
        public void GetPostsFromSpecificAuthorWhereNotBlogOwner()
        {
            var requestedAuthor = dataStructure.Authors["mark"];

            var selectedPosts = 
            (
                dataStructure.Posts.SelectMany(
                    post => dataStructure.Blogs, 
                    (post, blog) => new
                    {
                        post, blog
                    }
                ).Where(
                    @t => @t.post.Value.Author == requestedAuthor
                          && @t.blog.Owner != requestedAuthor
                          && @t.blog.Posts.Contains(@t.post.Value)
                ).Select(
                    @t => new
                    {
                        @t.post.Value,
                        @t.blog
                    }
                )
            ).ToList();

            selectedPosts.ForEach(x => 
                Console.WriteLine("- " + 
                    x.Value.Title + " by " + 
                    x.Value.Author.AuthorName + " on " + 
                    x.blog.BlogName));
        }
    }
}


Hope you enjoyed this.

-Mark

Wednesday, November 26, 2008

Being Specific with your Generics – Visitor Pattern without the Visitors

Generics are very useful when you have a particular functionality / logic that you want to apply on different types. Instead of having to duplicate the functionality for all your types you can put it in a generic class / method and have all the different types use it. One of the most used examples of this I think is it List<T> this is basically a strongly typed list that can be used for any type, and it works the same for any type.

This is great, but… (yes there is a but), what if what you have is 90% generic and 10% specific to the provided type, lets walk through an example that I encountered when working with Castle ActiveRecord. Each Business Data Object that you want to persist to the database using Castle ActiveRecord needs to be derived from ActiveRecordBase<T> where T is the derived class. This gives certain default functionality to each derived object like Save(). I’ll use the Blog and Post analogy that Ayende uses a lot too as it makes sense.

class Blog : ActiveRecordBase
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using Castle.ActiveRecord;

namespace Fohjin.SpecificWithGenerics
{
    [ActiveRecord]
    public class Blog : ActiveRecordBase<Blog>
    {
        [PrimaryKey]
        public virtual int Id { get; set; }
        [Property]
        public string Name { get; set; }
        [Property]
        public string Author { get; set; }
        [HasMany(typeof(Post))]
        public IList<Post> Posts { get; set; }
    }
}



Post : ActiveRecordBase
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using Castle.ActiveRecord;

namespace Fohjin.SpecificWithGenerics
{
    [ActiveRecord]
    public class Blusing Castle.ActiveRecord;

namespace Fohjin.SpecificWithGenerics
{
    [ActiveRecord]
    public class Post : ActiveRecordBase<Post>
    {
        [PrimaryKey]
        public virtual int Id { get; set; }
        [Property]
        public virtual string PostId { get; set; }
        [BelongsTo("BlogId")]
        public virtual Blog Blog { get; set; }
        [Property]
        public string Title { get; set; }
        [Property]
        public string Content { get; set; }
    }
}
og : ActiveRecordBase<Blog>
    {
        [PrimaryKey]
        public virtual int Id { get; set; }
        [Property]
        public string Name { get; set; }
        [Property]
        public string Author { get; set; }
        [HasMany(typeof(Post))]
        public IList<Post> Posts { get; set; }
    }
}


Now that this is working fine, we wanted to add some generic functionality to both classes, a GetOrCreate (object id) method, which as the name already specifies tries to get an items based on the provided Id from the datebase and if that fails create a new one. So I created a RepositoryItemBase<T> class:

class RepositoryItemBase : ActiveRecordBase where T : class, new()
1
2
3
4
5
6
7
8
9
10
11
12
13
using Castle.ActiveRecord;

namespace Fohjin.SpecificWithGenerics
{
    public class RepositoryItemBase<T> : ActiveRecordBase<T> where T : class, new()
    {
        public T GetOrCreate(object id)
        {
            return Find(id) ?? new T();
        }
    }
}


So instead of having our Business Data Objects inherit from ActiveRecordBase<T> they will inherit from RepositoryItemBase<T> that inherits from ActiveRecordBase<T> again. Thus in affect extending the ActiveRecordBase<T> with the GetOrCreate functionality.

Now this works all fine, except that our Post class has a PostId which is not the PrimaryKey, but this is the key that is used to find the blog posts. This means that we need to specifically handle some generic types different than others. In my example I only have one extension and you could argue to add that method to the actual Business Data Objects, but in our solution we have many more Business Data Objects and there are only a few different GetOrCreate variants. And there are more generic extension methods. I could also create new derived objects from RepositoryItemBase<T> and have the specific functionality in there, but that didn’t look to appealing to me. So here is my implementation using an adapted Visitor Pattern using a bit like a very simple IoC container and Delegates.

class RepositoryItemBase : ActiveRecordBase where T : class, new()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using System;
using System.Collections.Generic;
using Castle.ActiveRecord;

namespace Fohjin.SpecificWithGenerics
{
    public class RepositoryItemBase<T> : ActiveRecordBase<T> where T : class, new()
    {
        private readonly IDictionary<Type, Func<object, T>> delegatesByType;

        public RepositoryItemBase()
        {
            delegatesByType = new Dictionary<Type, Func<object, T>>();
            InitializeDelegatesByType();
        }

        public T GetOrCreate(object id)
        {
            if (!delegatesByType.ContainsKey(typeof(T)))
                throw new TypeLoadException("The provided type \"{0}\" is not supported!", typeof(T).ToString());

            return delegatesByType[typeof(T)].Invoke(id);
        }

        private void InitializeDelegatesByType()
        {
            delegatesByType.Add(typeof(Blog), x => Find(x) ?? new T());
            delegatesByType.Add(typeof(Post), x =>
            {
                var posts = FindAllByProperty("PostId", x);
                if (posts.Length > 0)
                {
                    return posts[0];
                }
                return new Post { PostId = x.ToString() } as T;
            });
        }
    }
}


As you can see I added a IDictionary<Type, Func<object, T>> this is for the IoC principle but instead of returning an object for a specific type it returns a function. This is where the Visitor Pattern comes into play, you define specific logic for each type, just like you would define a Visitor for each type, but instead of creating the different Visitor classes I defined different delegates with the same signature.

edit
I got some comments from people about something I did know, but maybe didn’t want to see :) the class RepositoryItemBase is violating the Open Closed Principle (OCP). As I also explain in a comment to Raymond we moved away from Castle ActiveRecord:

The main reason we were using Castle ActiveRecord was because we could configure our NHibernate mappings using Attributes instead of writing XML. But how Castle ActiveRecord places all the extra logic in the data containers was bothering us on different areas. I want the application to have a single point to do any data related tasks so I ended up with ugly methods that were like this: public class Repository { public void Save(ActiveRecordBase entity) { entity.Save(); } }

So I re-factored Castle ActiveRecord out of the solution and started using Fluent NHibernates AutoMap functionality for the mapping and DB schema generation (while developing) and plain NHibernate for the persistence tasks, much cleaner.

I also re-factored the non primary key name to be SourceId and placed this in the following interface:

interface IRepositoryItemWithSourceId
1
2
3
4
5
6
7
namespace Fohjin.SpecificWithGenerics
{
    public interface IRepositoryItemWithSourceId
    {
        string SourceId { get; set; }
    }
}

Now all the Business Data Objects that have this special Id need to inherit from this interface, and that lets me do to following thing:

class Repository : IRepository
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
using FluentNHibernate.Framework;
using InfoDoc.Server.BL.BDO.Interfaces;
using NHibernate;
using NHibernate.Criterion;

namespace Fohjin.SpecificWithGenerics
{
    public class Repository : IRepository
    {
        private readonly ISessionSource sessionSource;

        public Repository(ISessionSource source)
        {
            sessionSource = source;
        }
        public IList<T> Query<T>(Expression<Func<T, bool>> function)
        {
            ISession session = sessionSource.CreateSession();
            FluentNHibernate.Framework.IRepository nHibernateRepository = new FluentNHibernate.Framework.Repository(session);
            return nHibernateRepository.Query(function);
        }

        public T GetOrCreate<T>(object id) where T : class, IRepositoryItemWithSourceId, new()
        {
            var items = Query<T>(r => r.SourceId == id.ToString());
            return items.Count > 0 ? items[0] : new T { SourceId = id.ToString() };
        }
    }
}


As you can see now we are talking Generics again and don't have any dirty techniques to threat a generic value in a specific way. I do plan to explore the technique that Raymond suggested as well as a technique John suggested in a feature post, but for this problem the current solution is probably the best.

I hope you found this useful and as always if it can be improved please let me know.

-Mark

NNUG – TFS With Terje Sandstrøm

Last night was again a very interesting NNUG meeting this time with Terje Sandstrøm and the topic this day was TFS and how to use TFS in a Continuous Integration process. There were many things that I didn’t know yet and many Aha moments during the presentation. I also heard from other attendees that they would be applying the newly learned knowledge in their own environment right away.

And as usual the day didn’t end after the presentation, a couple of guys went with Terje to a pub to get some very interesting discussions going, I remember going home quite late. You can follow Terje on his blog http://geekswithblogs.net/terje/Default.aspx

-Mark

Tuesday, November 25, 2008

Announcing Isolator for Sharepoint : Unit testing for sharepoint made easier (and a free license!)

Typemock are offering their new product for unit testing SharePoint called Isolator For SharePoint, for a special introduction price. it is the only tool that allows you to unit test SharePoint without a SharePoint server. To learn more click here.

The first 50 bloggers who blog this text in their blog and tell us about it, will get a Full Isolator license, Free. for rules and info click here.

This is a great change to gain some experiance with Typemock -Mark

Monday, October 27, 2008

Arnon Rotam-Gal-Oz talks about: ”Architect Soft Skills”

This is a very interesting article about the non technical skills an Architect should have: http://www.rgoarchitects.com/nblog/2008/10/26/ArchitectSoftSkills.aspx

Go ahead and read it.

Saturday, October 25, 2008

What tools I use when developing software

Gøran Hansen was so kind to tag me with a question what kind of tools I use when developing software. Well looking at his post and at Lars Wilhelmsen, who started this series, post I am not so much a tools kind of guy I guess :)

The new .Net Framework logo   Yay ReSharper

Basic tools:
Continuous Integration:
Information sources:
Currently looking into while reading “Building Domain Specific Languages in Boo”:
As for tagging others, I wouldn’t know who to tag, so I tag every reader of this blog :) (that should get at least two or three geeks) :)

Tuesday, October 21, 2008

Crack.Net by Josh Smith

Catchy name for a debugging tool :)

Ever needed to fix a bug that didn't happen on you development machine, but does in test (or production, but the disclaimer clearly states not to use it in production ;) well now you can try this new tool. It injects itself in a running .Net application and allows you to browse and change the objects in the managed heap of that _running_ application.

http://joshsmithonwpf.wordpress.com/2008/10/21/new-release-of-cracknet-on-codeplex/
http://joshsmithonwpf.wordpress.com/cracknet/

A more detailed article about Crack.Net

http://joshsmithonwpf.files.wordpress.com/2008/10/cracknet-article1.doc

-Mark

Thursday, October 16, 2008

James Kovacs talks about ” Roll-Your-Own IoC” on dnrTV

Here is a very interesting video about Dependency Injection (DIP), Inversion of Control (IoC), Test Driven Development (TDD) and how to write your own simple IoC container. And along the way you'll see some cool R# tricks. This is one of the basis NDA stands on and this is a really clear and easy step through conversation on how to implement DIP, and understand the ideas behind it.

http://codebetter.com/blogs/james.kovacs/archive/2008/10/15/dnrtv-episode-126-roll-your-own-ioc-with-me.aspx

Go Watch it!

Friday, October 10, 2008

My ToDo list

I have too many projects right now:

  • Currently reading “Building Domain Specific Languages in Boo” from Ayende Rahien. This is a very interesting book and I’ll definitely write some blog posts about that.
  • NDA, thinking what the next post should be about, I like to explain by example so finding a good example is the next step.
  • A friend of mine is creating a new design for my blog; this is becoming very cool, not as corny as this current look (I don’t dare calling the current one a design).
  • Converting the new blog to Community Server Express edition
  • Unit testing XAML definitions, I need to finish that.
And these are only the technical projects that I am talking about; there is also the family :)

Wednesday, October 1, 2008

New design of my blog

I just created a quick new design for my blog because I didn't like the way the Blogger templates look. So let me know what you think. I am also looking into the free version of Community Server, but those guys take more than 2 day to send me a download link :(

Monday, September 29, 2008

Is NDA in conflict with YAGNI?

I got a question on my previous post (The No Dependency Architecture (NDA)) if NDA is not in conflict with YAGNI, and when I was writing the response it became more or less an actual post, so there you go :)

Explaining the thought behind the No Dependency Architecture (NDA) in combination with YAGNI in one sentence would be something like this: “You anticipate change at a technical level, not at a functional level”.

I believe that the “You Ain’t Gonna Need It” (YAGNI) principle does not imply that writing software accordingly to the SOLID principles is bad practice. When you are following these principles (and there are others that are good to follow too) then you are writing software that assumes change, right? I believe that YAGNI is more targeted to functional overhead.

I.e. using a IoC container to fulfill the Dependency Inversion Principle (DIP) is not in conflict with YAGNI because that is at a technical level, but when you are writing extra code for no other reason than that you assume the object might be used in a certain other way also, then you are violating the YAGNI principle because then you are creating additional functionality that is not needed.

From Wikipedia ( http://en.wikipedia.org/wiki/You_Ain't_Gonna_Need_It) YAGNI, short for 'You Ain't Gonna Need It', suggests to programmers that they should not add functionality until it is necessary

So I would recommend using the various SOLID principles when writing your software assuming things will change because that is just good practice. Change is a fact, we just don’t know what will change, but by conforming to SOLID we can handle these future changes without too much headache.

As to using an Event Driven Architecture, I am surely not saying each object should only interact using events, that would not make much sense, but most (larger) systems will be build up using multiple sub systems. Having these sub systems communicate via events is a very good way to isolate them from each other. Then it is unknown to each sub system who they are really talking to (i.e. dispatching the events to). In fact it is a 1 to n relationship where the dispatched event might have no, one or many subscribers.

To make the actual handling of subscribing and publishing easier you could use a service bus that deal with that for you. This will also make the system easier adaptable to change. You can also specify that the event can be handled by any instance of the same subscriber enabling load balancing.

“Don’t call us, we call you” ( http://en.wikipedia.org/wiki/Hollywood_Principle); is the basis of an Event Driven Architecture, and this is very true, because no system is waiting on an answer from another system. They fire events and they act on events, it is merely coincidence if these events have anything to do with each other.

So I would also recommend using an Event Driven Architecture (EDA) straight from the beginning, perhaps not using a service bus from the start, but just using EDA will make refactoring to use one at a later stage a lot easier.

Thursday, September 25, 2008

The No Dependency Architecture (NDA)

We already have many, many, many acronyms in our profession; TDD, BDD, DDD, SOA, EDA, DIP and SOLID just to name a few. So who am I to add yet another one in the mix, well I am a nobody. Having covered that, I would like to continue explaining this new one.

NDA is a software architecture that has no dependencies between the different components. It’s all in the name :)

By combining the Dependency Inversion Principle (DIP) and an Event Driven Architecture (EDA) we can achieve software that has no dependencies, not internal not external. So why would we want that? Well it enables you to just replace any part in your software solution with something else without it affecting the rest of the solution. And you will be able to scale the solution much easier.

So let’s look a bit more into the details, first I would like to start with DIP. Dependency Injection can be achieved using an Inversion of Control (IoC) container. An IoC container will provide an already instantiated object that (when done properly according to DIP) is based on an interface. The consumer of the object is only using the interface and does not know anything about the actual implementation.

One simple rule about how to provide the dependent objects is that when the consumer object cannot work without the dependent object it should be provided in the constructor of the consumer object; if the consumer object can continue without the dependent object (i.e. logging module) than that object should be provided via a setter property of the consumer object.

Modern IoC containers can Auto Wire the dependencies when creating an object, meaning that if a object of the requested type is present in the configuration you will not have to specify the dependent object in the constructor arguments of the consumer, this will be done automatically. I am a fan of keeping the configuration of the IoC container in a configuration file, this way I can easily provide a different implementation of the requested objects by just changing the configuration file. No need to recompile anything. I currently am working a lot with Castle Windsor which is a great IoC container.

So this should take care of dependencies your code may have between other parts of your code (i.e. object between object). Now we can move on to try and get rid of dependencies between different systems or major parts of your system (i.e. between services and consumers). When using an Event Driven Architecture your code is basically sending out events when something happens and does not care who or what is acting on those events. Different systems may subscribe to these events and may do their own thing. And to take this one step further you should consider using a service bus architecture, which basically means that events will be published into a cue. Consumers of these events subscribe to the cue and will get notified whenever there is an event waiting for them. There can be as many consumers subscribing to the events via the service bus as needed. The publisher does not know nor care about the consumers; it fires the event and moves on. Consumers don’t know or care about the source of the event, just that it is the type of event they are interested in.

As you can see this decouples the different systems from each other, since none of them know about each other there can be no dependencies between each other. Currently I am looking into NServiceBus, I got a real nice demo today from my college John that started this current thought process.

So now I believe we have a system that does not depend on anything, well realistically it depends on things, but these things can be switched, replaced, multiplied and even be offline nobody knows. I plan to go over these different parts in the coming posts, so if you have any comment I would love to hear from you.

Castle Windsor http://www.castleproject.org/container/index.html
NServiceBus http://www.nservicebus.com/

Wednesday, September 24, 2008

Silverlight with Einar Ingebrigtsen from Objectware

Today was another interesting NNUG (Norwegian .Net User Group) meeting where Einar presented Silverlight 2 in two separate sessions.

The first session covered more how easy it is to get a nice look and feel, together with some nice animations. During this presentation Einar used both Visual Studion 2008 and Expression Blend 2.5, and demonstrated how well they work together.

The second session was more technical and went into using WCF (Windows Communication Foundation) to have the Silverlight application communicate with the server. This session was very code driven and that was great about it. He demonstrated how to create the WCF service using a Visual Studio file template, I don’t know the exact name for it, but similar to creating a new class he created a new Silverlight WCF services, and how to consume it in the WCF code. Btw there is nothing special about a Silverlight WCF services except that it is using the BasicHTTPBinding

Einar Ingebrigtsen http://www.ingebrigtsen.info/

Saturday, September 20, 2008

That Agile Thing

I think he nailed it, doesn't matter what mythologies (pun intended) you are using, it is about delivering required functionality to your customer. And doing that in small iterations has been proven to work.

http://ayende.com/Blog/archive/2008/09/20/that-agile-thing.aspx

-Mark

How to test your XAML Behavior using unit tests

With WPF and Silverlight a whole new area opens up for application development. Using XAML it is so much easier to create something ‘Cool’ than was possible before with ‘normal’ Windows Forms. Another even more important thing is the separation of the GUI and the application code; this makes testing more easily because you have a clear cut line between your GUI and code. Not to mention much more maintainable and extendable. There are many more good reasons why you might want to use WPF or Silverlight instead of the previous technologies, but going back to the ‘Cool’ part. Now It is also very possible that I as a developer create an extremely simple GUI just to verify some needed functionality and then move on to the actual code. In the meantime we send the XAML file to our design department and they start working on actually making it ‘Cool’, because be honest; no matter how easy they make it for me, I will never be able to create a cool graphical design ;) So also for this example I shamelessly took something that I think looks cool from Gøran Hansen from the MSDN Live presentations he is keeping in Norway.

Anyway below here is a screenshot of a Window that Gøran Hansen created, I only converted it to a UserControl and changed the behavior to be in the XAML definition without external data binding.

XAML UserControl


I just noticed that images are not provided to the Google Reader so if you are missing these just go to the original post.

So the XAML file gets returned to me by one of our graphical designers and now I have to check that all the previous existing functionality is still there and working. So what I really want to be able to do is replace my original file with the new one and have some tests run to verify that all my functionality still is valid. I want unit tests for my XAML Behavior.

XAML UserControl Unit tests


XAML Behavior, didn’t you just say that the GUI is now separated from the application code, so it should also be separated from any behavior right? Well no not exactly, we can still define some logic in the XAML definition, quite a lot actually. If this is something we want is another discussion, let’s assume because it is possible it will be used ;) So I did define some basic behavior in my XAML definition, namely: • I wanted the Save button to be disabled until both the Web Dashboard URL and the Poll interval where filled in. • I wanted to only be able to select a successful build sound file when the user check that option, the same for the broken build sound file. So this behavior is independent of any code or other logic than is defined in the XAML definition. Ok I admit I wrote a small convertor that is used in the XAML definition, but that is more an XAML extension.

So when I received the new design from our graphics department it looked like this:

XAML UserControl


Ok this didn’t actually go to them ;) this is me being creative, but in the process of making these huge changes to the design I broke some of the previous behavior, behavior that I am counting on to work. For example I don’t want users to click the Save button before they filled out the needed information? So how do I know I broke these behaviors? Well look at the following screenshot, isn’t that a clear picture?

XAML UserControl Unit tests


So finally I get to the interesting parts, how did I get Unit testing for my XAML Behavior? For this I wrote a really simple helper class that is responsible for loading and parsing the XAML. This helper class is then used in the unit testing framework of your choice; I used NUnit in this example.

Class: XamlUnitTestHelper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Threading;

namespace Fohjin.XamlBehaviorVerifier
{
    /// <summary>
    /// This is a static helper class to use with any unit testing framework.
    /// </summary>
    public static class XamlUnitTestHelper
    {
        private static ParserContext _XamlContext;
        private static Viewbox _Viewbox;

        /// <summary>
        /// Loads the xaml into a Viewbox so that we can parse it and verify its working.
        /// </summary>
        /// <param name="xamlFilePath">The xaml file path.</param>
        public static void LoadXaml(string xamlFilePath)
        {
            String xamlFileStream = File.ReadAllText(xamlFilePath);
            if (xamlFileStream.IndexOf("x:Class=") != -1)
                xamlFileStream = Regex.Replace(xamlFileStream, "x:Class=\\\".+([^\\\"])\\\"", "");

            object obj = XamlReader.Load(new MemoryStream(new System.Text.ASCIIEncoding().GetBytes(xamlFileStream)), XamlContext);
            _Viewbox = new Viewbox
            {
                Child = ((UIElement)obj)
            };
            _Viewbox.UpdateLayout();
            FlushDispatcher();
        }

        /// <summary>
        /// Gets the object.
        /// </summary>
        /// <typeparam name="T">This is the type of control that is being searched for</typeparam>
        /// <param name="name">The name of the control that is being searched for</param>
        /// <returns>If the control is found a reference to this control is returned else null</returns>
        public static T GetObject<T>(string name) where T : class
        {
            if (_Viewbox != null && _Viewbox.Child != null)
            {
                FrameworkElement child = _Viewbox.Child as FrameworkElement;
                if (child != null)
                {
                    return child.FindName(name) as T;
                }
            }
            return null;
        }

        /// <summary>
        /// Gets the xaml context, to be used by the XamlReader.
        /// </summary>
        /// <value>The xaml context.</value>
        private static ParserContext XamlContext
        {
            get
            {
                if (_XamlContext == null)
                {
                    _XamlContext = new ParserContext();
                    _XamlContext.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
                }
                return _XamlContext;
            }
        }
        /// <summary>
        /// Flushes the dispatcher, needed to get data binding working when the control is not actually rendered to screen
        /// </summary>
        private static void FlushDispatcher()
        {
            FlushDispatcher(Dispatcher.CurrentDispatcher);
        }
        /// <summary>
        /// Flushes the dispatcher, needed to get data binding working when the control is not actually rendered to screen
        /// </summary>
        private static void FlushDispatcher(Dispatcher ctx)
        {
            FlushDispatcher(ctx, DispatcherPriority.SystemIdle);
        }
        /// <summary>
        /// Flushes the dispatcher, needed to get data binding working when the control is not actually rendered to screen
        /// </summary>
        private static void FlushDispatcher(Dispatcher ctx, DispatcherPriority priority)
        {
            ctx.Invoke(priority, new DispatcherOperationCallback(delegate { return null; }), null);
        }
    }
}

As you can see it is really simple and straightforward, the FlushDispatcher is something I need for Data Binding this is I discussed in a previous post Saving a WPF Xaml FlowDocument to XPS with working DataBinding. I am not using Data Binding in this example, but in a next post I’ll see if I can get that to work also.

Class: SettingsUserControlTests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
using System.Windows.Controls;
using Fohjin.XamlBehaviorVerifier;
using NUnit.Framework;

namespace WpfControlLibrary.Test
{
    [TestFixture]
    public class SettingsUserControlTests
    {
        private const string _XamlFilePath = @"C:\Projects\Fohjin.XamlTest\WpfControlLibrary\SettingsUserControl1.xaml";
        //private const string _XamlFilePath = @"C:\Projects\Fohjin.XamlTest\WpfControlLibrary\SettingsUserControl2.xaml";

        private const string _SoundsCheckBox = "soundsCheckBox";
        private const string _SoundsCheckBoxNotFound = "Could not find CheckBox control '" + _SoundsCheckBox + "'";
        private const string _SoundsCheckBoxIssue = "Issue with a value of '" + _SoundsCheckBox + "'";

        private const string _BrokenCheckBox = "brokenCheckBox";
        private const string _BrokenCheckBoxNotFound = "Could not find CheckBox control '" + _BrokenCheckBox + "'";
        private const string _BrokenCheckBoxIssue = "Issue with a value of '" + _BrokenCheckBox + "'";

        private const string _BtnOnSuccessFileDialog = "btnOnSuccessFileDialog";
        private const string _BtnOnSuccessFileDialogNotFound = "Could not find Button control '" + _BtnOnSuccessFileDialog + "'";
        private const string _BtnOnSuccessFileDialogIssue = "Issue with a value of '" + _BtnOnSuccessFileDialog + "'";
        
        private const string _BtnOnBrokenFileDialog = "btnOnBokenFileDialog";
        private const string _BtnOnBrokenFileDialogNotFound = "Could not find Button control '" + _BtnOnBrokenFileDialog + "'";
        private const string _BtnOnBrokenFileDialogIssue = "Issue with a value of '" + _BtnOnBrokenFileDialog + "'";

        private const string _TxtWebDashboardUrl = "txtWebDashboardUrl";
        private const string _TxtWebDashboardUrlNotFound = "Could not find TextBox control '" + _TxtWebDashboardUrl + "'";
        //private const string _TxtWebDashboardUrlIssue = "Issue with a value of '" + _TxtWebDashboardUrl + "'";

        private const string _TxtPollInterval = "txtPollInterval";
        private const string _TxtPollIntervalNotFound = "Could not find TextBox control '" + _TxtPollInterval + "'";
        //private const string _TxtPollIntervalIssue = "Issue with a value of '" + _TxtPollInterval + "'";

        private const string _BtnSave = "btnSave";
        private const string _BtnSaveNotFound = "Could not find Button control '" + _BtnSave + "'";
        private const string _BtnSaveIssue = "Issue with a value of '" + _BtnSave + "'";

        [Test]
        public void VerifyThatbtnOnSuccessFileDialogIsDisabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnSuccessFileDialog);
            Assert.IsNotNull(button, _BtnOnSuccessFileDialogNotFound);
            Assert.IsFalse(button.IsEnabled, _BtnOnSuccessFileDialogIssue);
        }
        [Test]
        public void VerifyThatbtnOnSuccessFileDialogIsEnabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            CheckBox checkBox = XamlUnitTestHelper.GetObject<CheckBox>(_SoundsCheckBox);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnSuccessFileDialog);

            Assert.IsNotNull(button, _BtnOnSuccessFileDialogNotFound);
            Assert.IsNotNull(checkBox, _SoundsCheckBoxNotFound);

            checkBox.IsChecked = true;
            Assert.IsTrue(button.IsEnabled, _BtnOnSuccessFileDialogIssue);
        }
        [Test]
        public void VerifyThatbtnOnSuccessFileDialogIsDisabledAgain()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            CheckBox checkBox = XamlUnitTestHelper.GetObject<CheckBox>(_SoundsCheckBox);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnSuccessFileDialog);

            Assert.IsNotNull(button, _BtnOnSuccessFileDialogNotFound);
            Assert.IsNotNull(checkBox, _SoundsCheckBoxNotFound);

            Assert.IsFalse(checkBox.IsChecked.Value, _SoundsCheckBoxIssue);
            Assert.IsFalse(button.IsEnabled, _BtnOnSuccessFileDialogIssue);

            checkBox.IsChecked = true;
            Assert.IsTrue(checkBox.IsChecked.Value, _SoundsCheckBoxIssue);
            Assert.IsTrue(button.IsEnabled, _BtnOnSuccessFileDialogIssue);

            checkBox.IsChecked = false;
            Assert.IsFalse(checkBox.IsChecked.Value, _SoundsCheckBoxIssue);
            Assert.IsFalse(button.IsEnabled, _BtnOnSuccessFileDialogIssue);
        }

        [Test]
        public void VerifyThatbtnOnBrokenFileDialogIsDisabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnBrokenFileDialog);
            Assert.IsNotNull(button, _BtnOnBrokenFileDialogNotFound);
            Assert.IsFalse(button.IsEnabled, _BtnOnBrokenFileDialogIssue);
        }
        [Test]
        public void VerifyThatbtnOnBrokenFileDialogIsEnabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            CheckBox checkBox = XamlUnitTestHelper.GetObject<CheckBox>(_BrokenCheckBox);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnBrokenFileDialog);

            Assert.IsNotNull(button, _BtnOnBrokenFileDialogNotFound);
            Assert.IsNotNull(checkBox, _BrokenCheckBoxNotFound);

            checkBox.IsChecked = true;
            Assert.IsTrue(button.IsEnabled, _BtnOnBrokenFileDialogIssue);
        }
        [Test]
        public void VerifyThatbtnOnBrokenFileDialogIsDisabledAgain()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            CheckBox checkBox = XamlUnitTestHelper.GetObject<CheckBox>(_BrokenCheckBox);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnOnBrokenFileDialog);

            Assert.IsNotNull(button, _BtnOnBrokenFileDialogNotFound);
            Assert.IsNotNull(checkBox, _BrokenCheckBoxNotFound);

            Assert.IsFalse(checkBox.IsChecked.Value, _BrokenCheckBoxIssue);
            Assert.IsFalse(button.IsEnabled, _BtnOnBrokenFileDialogIssue);

            checkBox.IsChecked = true;
            Assert.IsTrue(checkBox.IsChecked.Value, _BrokenCheckBoxIssue);
            Assert.IsTrue(button.IsEnabled, _BtnOnBrokenFileDialogIssue);

            checkBox.IsChecked = false;
            Assert.IsFalse(checkBox.IsChecked.Value, _BrokenCheckBoxIssue);
            Assert.IsFalse(button.IsEnabled, _BtnOnBrokenFileDialogIssue);
        }

        [Test]
        public void VerifyThatbtnSaveIsDisabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsFalse(button.IsEnabled, _BtnSaveIssue);
        }
        [Test]
        public void VerifyThatbtnSaveIsDisabled1()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            TextBox txtWebDashboardUrl = XamlUnitTestHelper.GetObject<TextBox>(_TxtWebDashboardUrl);
            TextBox txtPollInterval = XamlUnitTestHelper.GetObject<TextBox>(_TxtPollInterval);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsNotNull(txtWebDashboardUrl, _TxtWebDashboardUrlNotFound);
            Assert.IsNotNull(txtPollInterval, _TxtPollIntervalNotFound);

            txtWebDashboardUrl.Text = "test text";
            txtPollInterval.Text = "";
            Assert.IsFalse(button.IsEnabled, _BtnSaveIssue);
        }
        [Test]
        public void VerifyThatbtnSaveIsDisabled2()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            TextBox txtWebDashboardUrl = XamlUnitTestHelper.GetObject<TextBox>(_TxtWebDashboardUrl);
            TextBox txtPollInterval = XamlUnitTestHelper.GetObject<TextBox>(_TxtPollInterval);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsNotNull(txtWebDashboardUrl, _TxtWebDashboardUrlNotFound);
            Assert.IsNotNull(txtPollInterval, _TxtPollIntervalNotFound);

            txtWebDashboardUrl.Text = "";
            txtPollInterval.Text = "10";
            Assert.IsFalse(button.IsEnabled, _BtnSaveIssue);
        }
        [Test]
        public void VerifyThatbtnSaveIsEnabled()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            TextBox txtWebDashboardUrl = XamlUnitTestHelper.GetObject<TextBox>(_TxtWebDashboardUrl);
            TextBox txtPollInterval = XamlUnitTestHelper.GetObject<TextBox>(_TxtPollInterval);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsNotNull(txtWebDashboardUrl, _TxtWebDashboardUrlNotFound);
            Assert.IsNotNull(txtPollInterval, _TxtPollIntervalNotFound);

            txtWebDashboardUrl.Text = "test text";
            txtPollInterval.Text = "10";
            Assert.IsTrue(button.IsEnabled, _BtnSaveIssue);
        }
        [Test]
        public void VerifyThatbtnOnBrokenFileDialogIsDisabledAgain1()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            TextBox txtWebDashboardUrl = XamlUnitTestHelper.GetObject<TextBox>(_TxtWebDashboardUrl);
            TextBox txtPollInterval = XamlUnitTestHelper.GetObject<TextBox>(_TxtPollInterval);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsNotNull(txtWebDashboardUrl, _TxtWebDashboardUrlNotFound);
            Assert.IsNotNull(txtPollInterval, _TxtPollIntervalNotFound);

            txtWebDashboardUrl.Text = "test text";
            txtPollInterval.Text = "10";
            Assert.IsTrue(button.IsEnabled, _BtnSaveIssue);

            txtWebDashboardUrl.Text = "";
            Assert.IsFalse(button.IsEnabled, _BtnSaveIssue);
        }
        [Test]
        public void VerifyThatbtnOnBrokenFileDialogIsDisabledAgain2()
        {
            XamlUnitTestHelper.LoadXaml(_XamlFilePath);
            Button button = XamlUnitTestHelper.GetObject<Button>(_BtnSave);
            TextBox txtWebDashboardUrl = XamlUnitTestHelper.GetObject<TextBox>(_TxtWebDashboardUrl);
            TextBox txtPollInterval = XamlUnitTestHelper.GetObject<TextBox>(_TxtPollInterval);
            Assert.IsNotNull(button, _BtnSaveNotFound);
            Assert.IsNotNull(txtWebDashboardUrl, _TxtWebDashboardUrlNotFound);
            Assert.IsNotNull(txtPollInterval, _TxtPollIntervalNotFound);

            txtWebDashboardUrl.Text = "test text";
            txtPollInterval.Text = "10";
            Assert.IsTrue(button.IsEnabled, _BtnSaveIssue);

            txtPollInterval.Text = "";
            Assert.IsFalse(button.IsEnabled, _BtnSaveIssue);
        }
    }
}

Pretty cool and simple, right? Well you need to make sure that your unit tests are running in a ApartmentState.STA thread. When you are using NUnit you only need to add a configuration file to your test library with the following content:

App.Config file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <configSections>
  <sectionGroup name="NUnit">
   <section name="TestRunner" type="System.Configuration.NameValueSectionHandler"></section>
  </sectionGroup>
 </configSections>

 <NUnit>
  <TestRunner>
   <add key="ApartmentState" value="STA"></add>
  </TestRunner>
 </NUnit>
</configuration>
I intend to continue working on this a bit more too see how far I can take this without it becoming too big for unit testing. I hope you can also see the value in these types of tests. You can download the full solution from here: http://downloads.fohjin.com/Fohjin.XamlBehaviorTester.rar