Saturday, July 12, 2008

Saving a WPF Xaml FlowDocument to XPS with working DataBinding

I needed to create an invoice system, where the look and feel of the invoice could differ and also of course the invoice data would be different from invoice to invoice. After talking to a collega, whom pointed me into the direction of WPF Xaml FlowDocuments for templating the invoices, I started playing with them. So I created a template FlowDocument on which the actual invoice data would be placed and then saved as an XPS document for later use. But when saving the FlowDocument to an XPS file the databinding did not get triggered, it was basically just saving the template FlowDocument. I have read many examples on how to use databinding in a FlowDocument, but these where all when eventually printing the document to a printer, than everything works like a charm. Then you can use; Xaml inline recources, references to an external xml file or bind it with an object. So I continued my search and finally found the Microsoft Example (http://msdn.microsoft.com/en-us/library/ms771375.aspx) where they where able to save my FlowDocuments to an XPS file and keep databinding working properly. So I went through the code to see how it was done, wrote this in a library and will go through it here in this post.

First below here is the complete library that you will need to save a Xaml FlowDocument to XPS.

Class: XamlToXps
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
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Windows.Threading;
using System.Windows.Documents;
using System.Windows.Documents.Serialization;
using System.Windows.Markup;

namespace Fohjin.XamlLibrary
{
    /// <summary>
    /// Class that will take care of converting a Xaml WPF FlowDocument to a XPS document
    /// </summary>
    public class XamlToXps
    {
        /// <summary>
        /// Holds an internal copy of the Loaded Xaml
        /// </summary>
        private IDocumentPaginatorSource _FlowDocument;
        /// <summary>
        /// This Dictionary is used to perform string replacements in the source Xaml, 
        /// I use this f.ex. to replace an external default reference to an actual XML 
        /// file location
        /// </summary>
        private Dictionary<string, string> _StringReplacement;

        /// <summary>
        /// Initializes a new instance of the <see cref="XamlToXps"/> class.
        /// </summary>
        public XamlToXps()
        {
            _StringReplacement = new Dictionary<string, string>();
        }

        /// <summary>
        /// Gets or sets the string replacement dictionary later to be used for string 
        /// replacements in the Xaml source.
        /// </summary>
        /// <value>The string replacement dictionary.</value>
        public Dictionary<string, string> StringReplacement
        {
            set
            {
                _StringReplacement = value;
            }
            get
            {
                return _StringReplacement;
            }
        }

        /// <summary>
        /// Loads the source Xaml using a file location.
        /// At this stage there will be automatic string replacement.
        /// </summary>
        /// <param name="xamlFileName">Name of the xaml file.</param>
        public void LoadXaml(string xamlFileName)
        {
            using (FileStream inputStream = File.OpenRead(xamlFileName))
            {
                LoadXaml(inputStream);
            }
        }
        /// <summary>
        /// Loads the source Xaml using a Stream.
        /// At this stage there will be automatic string replacement.
        /// </summary>
        /// <param name="xamlFileStream">The xaml file stream.</param>
        public void LoadXaml(Stream xamlFileStream)
        {
            ParserContext pc = new ParserContext
            {
               BaseUri = new Uri(Environment.CurrentDirectory + "/")
            };
            object newDocument = XamlReader.Load(ReplaceStringsInXaml(xamlFileStream), pc);

            if (newDocument == null)
                throw new Exception("Invalid Xaml, could not be parsed");

            if (newDocument is IDocumentPaginatorSource)
                LoadXaml(newDocument as IDocumentPaginatorSource);
        }
        /// <summary>
        /// Loads the source Xaml in the form of a complete FlowDocument. 
        /// At this stage there is no automatic string replacement.
        /// </summary>
        /// <param name="flowDocument">The flow document.</param>
        public void LoadXaml(IDocumentPaginatorSource flowDocument)
        {
            _FlowDocument = flowDocument;
            FlushDispatcher();
        }

        /// <summary>
        /// Saves the prepared FlowDocument to a XPS file format.
        /// In this library there is only the XPS serializer, but in the Microsoft 
        /// example there are several, I still have to investigate how to get the others.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        public void Save(string fileName)
        {
            DeleteOldFile(fileName);
            FlowDocument flowDocument = _FlowDocument as FlowDocument;

            SerializerProvider serializerProvider = new SerializerProvider();
            SerializerDescriptor selectedPlugIn = null;
            foreach (SerializerDescriptor serializerDescriptor in serializerProvider.InstalledSerializers)
            {
                if (!serializerDescriptor.IsLoadable || !fileName.EndsWith(serializerDescriptor.DefaultFileExtension))
                    continue;
                selectedPlugIn = serializerDescriptor;
                break;
            }

            if (selectedPlugIn != null)
            {
                using (Stream package = File.Create(fileName))
                {
                    SerializerWriter serializerWriter = serializerProvider.CreateSerializerWriter(selectedPlugIn, package);
                    IDocumentPaginatorSource idoc = flowDocument;
                    if (idoc != null)
                        serializerWriter.Write(idoc.DocumentPaginator, null);
                    package.Close();
                }
            }
            else
                throw new Exception("No Serializer found for your requested output format");
        }

        /// <summary>
        /// Deletes the old output file if it exists.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        private static void DeleteOldFile(string fileName)
        {
            if (File.Exists(fileName))
            {
                File.Delete(fileName);
            }
        }

        /// <summary>
        /// Replaces the Key Value Pairs in the Xaml source, this is an other way of data 
        /// binding, but I prefere the build-in way.
        /// </summary>
        /// <param name="xamlFileStream">The xaml file stream.</param>
        /// <returns></returns>
        private Stream ReplaceStringsInXaml(Stream xamlFileStream)
        {
            string rawXamlText;
            xamlFileStream.Seek(0, SeekOrigin.Begin);
            using (StreamReader streamReader = new StreamReader(xamlFileStream))
            {
                rawXamlText = streamReader.ReadToEnd();
            }
            foreach (KeyValuePair<string, string> keyValuePair in _StringReplacement)
            {
                rawXamlText = rawXamlText.Replace(keyValuePair.Key, keyValuePair.Value);
            }
            return new MemoryStream(new UTF8Encoding().GetBytes(rawXamlText));
        }

        /// <summary>
        /// Have to figure out what this does and why it works, but not including 
        /// this and calling it wil actually fail the databinding process
        /// </summary>
        private static void FlushDispatcher()
        {
            FlushDispatcher(Dispatcher.CurrentDispatcher);
        }

        /// <summary>
        /// Have to figure out what this does and why it works, but not including 
        /// this and calling it wil actually fail the databinding process
        /// </summary>
        /// <param name="ctx"></param>
        private static void FlushDispatcher(Dispatcher ctx)
        {
            FlushDispatcher(ctx, DispatcherPriority.SystemIdle);
        }

        /// <summary>
        /// Have to figure out what this does and why it works, but not including 
        /// this and calling it wil actually fail the databinding process
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="priority"></param>
        private static void FlushDispatcher(Dispatcher ctx, DispatcherPriority priority)
        {
            ctx.Invoke(priority, new DispatcherOperationCallback(delegate { return null; }), null);
        }
    }
}

Well go through it, I’ll tell you what I found out when playing with the code and trying to get it to work:
  • You need to call the FlushDispatcher() method because else it won’t trigger the databinding process. This is something I have to look into why this is, but during my tests I definitely needed this. It is doing something with threading.
  • And the other thing is if you try to load a Xaml FlowDocument document using XamlReader.Load() method you will need to use the Stream version, and include a ParseContext object with a BaseUrl parameter. If you try to load the document straight from a file location it will not trigger the databinding process.
Now how to use this little library:
Usage
1
2
3
4
XamlToXps _XamlToXps = new XamlToXps();
_XamlToXps.StringReplacement.Add("[replace_with_content_location]", System.IO.Path.Combine(Environment.CurrentDirectory, "dataSource.xml"));
_XamlToXps.LoadXaml(System.IO.Path.Combine(Environment.CurrentDirectory, "FlowDocument.xaml"));
_XamlToXps.Save(System.IO.Path.Combine(Environment.CurrentDirectory, "dataSource.xps"));

I'll have to do some testing to see if this is working with data binding objects, but the other two mentioned options do work. I hope you found these examples helpful. Also take a look at the following links:

http://msdn.microsoft.com/en-us/library/ms771375.aspx
http://msdn.microsoft.com/en-us/library/aa970268.aspx
http://weblogs.asp.net/scottgu/archive/2007/02/22/wpf-text-reading-and-flow-document-support-and-the-new-nytimes-daily-mail-and-seattle-post-intelligencer-reader-applications.aspx
http://roecode.wordpress.com/category/xps/
http://blogs.msdn.com/fyuan/archive/2007/03/10/convert-xaml-flow-document-to-xps-with-style-multiple-page-page-size-header-margin.aspx

Monday, April 28, 2008

Composite Pattern

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. Say you have several different types of objects that together form a structure, for example a tree. Take a look at my example below:

Class: Branch
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
namespace Composite
{
    public class Branch
    {
        private readonly List<object> _Children;

        public Branch()
        {
            _Children = new List<object>();
        }

        public void Add(object item)
        {
            _Children.Add(item);
        }

        public void Display()
        {
            Display(1);
        }
        public void Display(int level)
        {
            Console.WriteLine(new string('-', level) + " Branch");
            level++;
            foreach (object child in _Children)
            {
                Branch branch = child as Branch;
                if (branch != null)
                {
                    branch.Display(level);
                    continue;
                }
                Leaf leaf = child as Leaf;
                if (leaf != null)
                {
                    leaf.Display(level);
                    continue;
                }
                Apple apple = child as Apple;
                if (apple != null)
                {
                    apple.Display(level);
                    continue;
                }
            }
        }
    }
}
Class: Leaf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace Composite
{
    public class Leaf
    {
        public void Display()
        {
            Display(1);
        }
        public void Display(int level)
        {
            Console.WriteLine(new string('-', level) + " Leaf");
        }
    }
}
Class: Apple
1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace Composite
{
    public class Apple
    {
        public void Display()
        {
            Display(1);
        }
        public void Display(int level)
        {
            Console.WriteLine(new string('-', level) + " Apple");
        }
    }
}
As you can see each object has a Display method, but the Display method of the Branch object is also calling its children’s Display method. And to be able to do that it needs to know what type of object it is. That results in the ugly if type name is object as type validation. The Composite Pattern is there to solve that. Take a look below:
Interface: IDisplayItem
1
2
3
4
5
6
7
8
namespace Composite
{
    public interface IDisplayItem
    {
        void Display();
        void Display(int level);
    }
}
Class: DisplayItem : IDisplayItem
1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace Composite
{
    public class DisplayItem : IDisplayItem
    {
        public virtual void Display()
        {
            Display(1);
        }
        public virtual void Display(int level)
        {
            throw new NotImplementedException();
        }
    }
}
Class: Branch : DisplayItem
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
namespace Composite
{
    public class Branch : DisplayItem
    {
        private readonly List<DisplayItem> _Children;

        public Branch()
        {
            _Children = new List<DisplayItem>();
        }

        public void Add(DisplayItem item)
        {
            _Children.Add(item);
        }

        public override void Display(int level)
        {
            Console.WriteLine(new string('-', level) + " Branch");
            level++;
            foreach (DisplayItem child in _Children)
            {
                child.Display(level);
            }
        }
    }
}
Class: Leaf : DisplayItem
1
2
3
4
5
6
7
8
9
10
namespace Composite
{
    public class Leaf : DisplayItem
    {
        public override void Display(int level)
        {
            Console.WriteLine(new string('-', level) + " Leaf");
        }
    }
}
Class: Apple : DisplayItem
1
2
3
4
5
6
7
8
9
10
namespace Composite
{
    public class Apple : DisplayItem
    {
        public override void Display(int level)
        {
            Console.WriteLine(new string('-', level) + " Apple");
        }
    }
}
See how much nicer this deals with the different child items? Now the Branch does not need to worry about what type of objects its children are, they all inherited from DisplayItem. I hope you found these examples helpful. Also take a look at the following links:

http://www.dofactory.com/Patterns/PatternComposite.aspx
http://sourcemaking.com/design_patterns/composite

Thursday, April 24, 2008

Specification Pattern using Spring.Net

After creating my previous post about the Specification Pattern I was thinking that it would be cool if we could use Spring.Net to actually provide the specification. Well after a little looking around I found the solution. I’ll only post the modifications that I made to the code from my last post. Take a look at the example below:

Class: SpecificationFactory
1
2
3
4
5
6
7
8
9
10
11
12
13
namespace Specification
{
    public class SpecificationFactory
    {
        public ISpecification GetSpecification()
        {
            using (IApplicationContext ctx = ContextRegistry.GetContext())
            {
                return (ctx.GetObject("Specification") as ISpecification);
            }
        }
    }
}
Class: SelectFromList
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
namespace Specification
{
    public class SelectFromList
    {
        private readonly List<IUser> _Users;

        public SelectFromList()
        {
            _Users = new List<IUser>();
            _Users.Add(new User() { FirstName="Mark", LastName="Nijhof", Age=31 });
            _Users.Add(new User() { FirstName = "Mona", LastName = "Nijhof", Age = 30 });
            _Users.Add(new User() { FirstName = "Milo", LastName = "Nijhof", Age = 2 });
            _Users.Add(new User() { FirstName = "Thalia", LastName = "Nijhof", Age = 1 });
        }

        public List<IUser> GetUsers(ISpecification specification)
        {
            List<IUser> result = new List<IUser>();
            foreach (IUser user in _Users)
            {
                if (specification.IsSatisfiedBy(user))
                {
                    result.Add(user);
                }
            }
            return (result);
        }
    }
}
File: App.Config
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
<configuration>
  <configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
    </sectionGroup>
  </configSections>

  <spring>
    <context>
      <resource uri="config://spring/objects" />
    </context>
    <objects xmlns="http://www.springframework.net">

      <object id="Specification" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
        <property name="TargetObject" ref="StartWith"/>
        <property name="TargetMethod" value="And"/>
        <property name="Arguments" ref="JongerThanWrapper" />
      </object>

      <object id="JongerThanWrapper" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
        <property name="TargetObject" ref="JongerThan"/>
        <property name="TargetMethod" value="Or"/>
        <property name="Arguments" ref="OlderThan" />
      </object>

      <object name="StartWith" type="Specification.StartWith, Specification" />
      <object name="OlderThan" type="Specification.OlderThan, Specification" />
      <object name="JongerThan" type="Specification.JongerThan, Specification" />
    </objects>
  </spring>
</configuration>
As you can see we created an extra class SpecificationFactory that would request the correct specification implementation from Spring.Net, we changed the GetUsers method from the SelectFromList class to use the SpecificationFactory class. Now take a close look at the App.Config, the object name that the SpecificationFactory is requesting is Specification. Specification is executing the 'And' method on object StartWith and is returning the value to the SpecificationFactory. As you may see the 'And' method is requiring another ISpecification object, it is pointing to JongerThanWrapper object. And so on until we get the exact same behavior that we had in my previous post, only now completely configurable using Spring.Net. Isn’t this great.

I hope you found these examples helpful. Also take a look at the following links:

http://www.springframework.net/
http://www.springframework.net/doc-1.1-P2/api/html/Spring.Objects.Factory.Config.MethodInvokingFactoryObject.html

Specification Pattern

The Specification pattern is a very powerful design pattern which can be used to remove a lot of cruft from a class’s interface while decreasing coupling and increasing extensibility. It’s primary use is to select a subset of objects based on some criteria, and to refresh the selection at various times. Take a look at the example below:

Interface: IUser
1
2
3
4
5
6
7
8
9
namespace Specification
{
    public interface IUser
    {
        string FirstName { get; set; }
        string LastName { get; set; }
        int Age { get; set; }
    }
}
Class: SelectFromList
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
namespace Specification
{
    public class SelectFromList
    {
        private readonly List<IUser> _Users;

        public SelectFromList()
        {
            _Users = new List<IUser>();
            _Users.Add(new User() { FirstName="Mark", LastName="Nijhof", Age=31 });
            _Users.Add(new User() { FirstName = "Mona", LastName = "Nijhof", Age = 30 });
            _Users.Add(new User() { FirstName = "Milo", LastName = "Nijhof", Age = 2 });
            _Users.Add(new User() { FirstName = "Thalia", LastName = "Nijhof", Age = 1 });
        }

        public List<IUser> GetUsers()
        {
            List<IUser> result = new List<IUser>();
            foreach (IUser user in _Users)
            {
                if (user.FirstName.StartsWith("M") &&
                    (user.Age > 10 || user.Age < 2))
                {
                    result.Add(user);
                }
            }
            return (result);
        }
    }
}
Below here you will see some preparation for the Specification Pattern, this might look like a lot of work but when dealing with a lot of these selection statements you will soon see the benefit of it, especially when you need to make changes to what you are selecting on.
Interface: ISpecification
1
2
3
4
5
6
7
8
9
10
11
namespace Specification
{
    public interface ISpecification
    {
        bool IsSatisfiedBy(IUser candidate);

        ISpecification And(ISpecification other);
        ISpecification Or(ISpecification other);
        ISpecification Not(ISpecification other);
    }
}
Class: Specification : ISpecification
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace Specification
{
    public class Specification : ISpecification
    {
        public virtual bool IsSatisfiedBy(IUser candidate)
        {
            throw new NotImplementedException();
        }
        public ISpecification And(ISpecification other)
        {
            return new AndSpecification(this, other);
        }
        public ISpecification Or(ISpecification other)
        {
            return new OrSpecification(this, other);
        }
        public ISpecification Not(ISpecification other)
        {
            return new NotSpecification(this, other);
        }
    }
}
Class: AndSpecification : Specification
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace Specification
{
    public class AndSpecification : Specification
    {
        private readonly ISpecification _One;
        private readonly ISpecification _Other;
        
        public AndSpecification(ISpecification one, ISpecification other)
        {
            _One = one;
            _Other = other;
        }

        public override bool IsSatisfiedBy(IUser candidate)
        {
            return _One.IsSatisfiedBy(candidate) && _Other.IsSatisfiedBy(candidate);
        }
    }
}
Class: OrSpecification : Specification
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace Specification
{
    public class OrSpecification : Specification
    {
        private readonly ISpecification _One;
        private readonly ISpecification _Other;

        public OrSpecification(ISpecification one, ISpecification other)
        {
            _One = one;
            _Other = other;
        }

        public override bool IsSatisfiedBy(IUser candidate)
        {
            return _One.IsSatisfiedBy(candidate) || _Other.IsSatisfiedBy(candidate);
        }
    }
}
Class: NotSpecification : Specification
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace Specification
{
    public class NotSpecification : Specification
    {
        private readonly ISpecification _One;
        private readonly ISpecification _Other;

        public NotSpecification(ISpecification one, ISpecification other)
        {
            _One = one;
            _Other = other;
        }

        public override bool IsSatisfiedBy(IUser candidate)
        {
            return _One.IsSatisfiedBy(candidate) && !_Other.IsSatisfiedBy(candidate);
        }
    }
}
Now take a look at how the Specification Pattern makes this much cleaner:
Class: StartWith : Specification
1
2
3
4
5
6
7
8
9
10
namespace Specification
{
    public class StartWith : Specification
    {
        public override bool IsSatisfiedBy(IUser candidate)
        {
            return (candidate.FirstName.StartsWith("M"));
        }
    }
}
Class: OlderThan : Specification
1
2
3
4
5
6
7
8
9
10
namespace Specification
{
    public class OlderThan : Specification
    {
        public override bool IsSatisfiedBy(IUser candidate)
        {
            return (candidate.Age > 10);
        }
    }
}
Class: JongerThan : Specification
1
2
3
4
5
6
7
8
9
10
namespace Specification
{
    public class JongerThan : Specification
    {
        public override bool IsSatisfiedBy(IUser candidate)
        {
            return (candidate.Age < 2);
        }
    }
}
Class: SelectFromList
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
namespace Specification
{
    public class SelectFromList
    {
        private readonly List<IUser> _Users;

        public SelectFromList()
        {
            _Users = new List<IUser>();
            _Users.Add(new User() { FirstName="Mark", LastName="Nijhof", Age=31 });
            _Users.Add(new User() { FirstName = "Mona", LastName = "Nijhof", Age = 30 });
            _Users.Add(new User() { FirstName = "Milo", LastName = "Nijhof", Age = 2 });
            _Users.Add(new User() { FirstName = "Thalia", LastName = "Nijhof", Age = 1 });
        }

        public List<IUser> GetUsers(ISpecification specification)
        {
            List<IUser> result = new List<IUser>();
            foreach (IUser user in _Users)
            {
                if (specification.IsSatisfiedBy(user))
                {
                    result.Add(user);
                }
            }
            return (result);
        }
    }
}
Usage
1
2
3
4
5
ISpecification startsWith = new StartWith();
ISpecification olderThan = new OlderThan();
ISpecification jongerThan = new JongerThan();

SFL.GetUsers(startsWith.And(olderThan.Or(jongerThan)));
When you look at the new SelectFromList class and how this is being used than you can see that it became much easier to extend or change the selection criteria.

I hope you found these examples helpful. Also take a look at the following links:

http://www.martinfowler.com/apsupp/spec.pdf
http://www.mattberther.com/2005/03/25/the-specification-pattern-a-primer/
http://en.wikipedia.org/wiki/Specification_pattern

Fluent Interfaces

What is a Fluent Interface, well is basically means that you can execute a method on an object and that that object would return itself to the caller, by doing so the client can chain multiple commands to each other. This will make the code (if implemented correctly) easier to read, please take a look at the example of a Fluent Interface below:

Interface: IOrder
1
2
3
4
5
6
7
8
9
namespace FluentInterfaces
{
    public interface IOrder
    {
        IOrder ShipAddress(IAddress address);
        IOrder BillAddress(IAddress address);
        IOrder AddItem(IItem item);
    }
}
Interface: IAddress
1
2
3
4
5
6
7
8
9
namespace FluentInterfaces
{
    public interface IAddress
    {
        IAddress Street(string street);
        IAddress PostalCode(string postalCode);
        IAddress City(string city);
    }
}
Interface: IOrder
1
2
3
4
5
6
7
8
9
namespace FluentInterfaces
{
    public interface IItem
    {
        IItem ProductID(int id);
        IItem Price(double price);
        IItem NubmerOfItems(int count);
    }
}
Class: Order : IOrder
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
namespace FluentInterfaces
{
    public class Order : IOrder
    {
        private IAddress _ShipAddress;
        private IAddress _BillAddress;
        private readonly List<IItem> _Items;

        public Order()
        {
            _Items = new List<IItem>();
        }

        public IOrder ShipAddress(IAddress address)
        {
            _ShipAddress = address;
            return (this);
        }
        public IOrder BillAddress(IAddress address)
        {
            _BillAddress = address;
            return (this);
        }
        public IOrder AddItem(IItem item)
        {
            _Items.Add(item);
            return (this);
        }
    }
}
Class: Address : IAddress
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
namespace FluentInterfaces
{
    public class Address : IAddress
    {
        private string _Street;
        private string _PostalCode;
        private string _City;

        public IAddress Street(string street)
        {
            _Street = street;
            return (this);
        }
        public IAddress PostalCode(string postalCode)
        {
            _PostalCode = postalCode;
            return (this);
        }
        public IAddress City(string city)
        {
            _City = city;
            return (this);
        }
    }
}
Class: Item : IItem
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
namespace FluentInterfaces
{
    public class Item : IItem
    {
        private int _Id;
        private double _Price;
        private int _Count;

        public IItem ProductID(int id)
        {
            _Id = id;
            return (this);
        }
        public IItem Price(double price)
        {
            _Price = price;
            return (this);
        }
        public IItem NubmerOfItems(int count)
        {
            _Count = count;
            return (this);
        }
    }
}
Class: Main
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
namespace FluentInterfaces
{
    class Program
    {
        static void Main(string[] args)
        {
            IOrder order = new Order()
                .ShipAddress(new Address()
                    .Street("Burggraaf 12")
                    .PostalCode("7371CW")
                    .City("Loenen"))
                .BillAddress(new Address()
                    .Street("Burggraaf 12")
                    .PostalCode("7371CW")
                    .City("Loenen"))
                .AddItem(new Item()
                    .ProductID(1)
                    .Price(15.40)
                    .NubmerOfItems(2))
                .AddItem(new Item()
                    .ProductID(132)
                    .Price(101.10)
                    .NubmerOfItems(1));
        }
    }
}
As you can see the actual creation of the Order and all of its properties has been simplified significantly and has improved readability. You can now directly see what this order is about. Indentation is only done for readability it could have been done like this:
Class: Main
1
2
3
4
5
6
7
8
9
10
namespace FluentInterfaces
{
    class Program
    {
        static void Main(string[] args)
        {
            IOrder order = new Order().ShipAddress(new Address().Street("Burggraaf 12").PostalCode("7371CW").City("Loenen")).BillAddress(new Address().Street("Burggraaf 12").PostalCode("7371CW").City("Loenen")).AddItem(new Item().ProductID(1).Price(15.40).NubmerOfItems(2)).AddItem(new Item().ProductID(132).Price(101.10).NubmerOfItems(1));
        }
    }
}
I hope you found these examples helpful. Also take a look at the following links:

http://martinfowler.com/bliki/FluentInterface.html
http://www.bofh.org.uk/articles/2005/12/21/fluent-interfaces

Wednesday, April 23, 2008

Adapter Pattern

The pattern states: the Adapter pattern adapts one interface for a class into one that a client expects. An adapter allows classes to work together that normally could not because of incompatible interfaces by wrapping its own interface around that of an already existing class. Take a look at the example below:

Class: Client
1
2
3
4
5
6
7
8
9
10
namespace Adapter
{
    public class Client
    {
        public void StartWorkerProcess(IWorker worker)
        {
            worker.StartWork();
        }
    }
}
Interface: IWorker
1
2
3
4
5
6
7
namespace Adapter
{
    public interface IWorker
    {
        void StartWork();
    }
}
Class: Worker : IWorker
1
2
3
4
5
6
7
8
9
10
namespace Adapter
{
    public class Worker : IWorker
    {
        public void StartWork()
        {
            Console.WriteLine("Start working");
        }
    }
}
Interface: IOtherWorker
1
2
3
4
5
6
7
namespace Adapter
{
    public interface IOtherWorker
    {
        void Start(string message);
    }
}
Class: OtherWorker : IOtherWorker
1
2
3
4
5
6
7
8
9
10
namespace Adapter
{
    public class OtherWorker : IOtherWorker
    {
        public void Start(string message)
        {
            Console.WriteLine("Start working on: " + message);
        }
    }
}
You can see that the client is expecting a class with a base type of IWorker and this works fine for the Worker class, but we already have another class OtherWorker in the system that has already implemented the behavior that we are looking for to extend the Client with. But this other worker is accordingly to the IOtherWorker interface, and we cannot change either class because both are already used in existing code (or perhaps the other worker is a third party product). So here comes the Adapter Pattern, take a look below how it will solve our problem:
Class: OtherWorkerAdapter : IWorker
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
namespace Adapter
{
    public class OtherWorkerAdapter : IWorker
    {
        private readonly IOtherWorker _OtherWorker;

        public OtherWorkerAdapter()
        {
            _OtherWorker = new OtherWorker();
        }

        public void StartWork()
        {
            _OtherWorker.Start("Initiated from OtherWorkerAdapter");
        }
    }
}
I hope you found these examples helpful. Also take a look at the following link:

http://www.dofactory.com/Patterns/PatternAdapter.aspx

Strategy Pattern

The pattern states: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. Look at the below example demonstrating a potential problem:

Class: Logger
1
2
3
4
5
6
7
8
9
10
namespace Strategy
{
    public class Logger
    {
        public void Log(string logMessage)
        {
            Console.WriteLine(logMessage);
        }
    }
}
You see that this is a really simple logging class logging messages to the console, but now we also want to be able to log to a file. Well you could add a new method to log to a file, but that would mean that all the classes using this Logger class has to change using the new method. So that is a no go. Take a look at the below example using the Strategy Pattern to make this possible without the need to change the client code:
Interface: ILogHandler
1
2
3
4
5
6
7
namespace Strategy
{
    public interface ILogHandler
    {
        void Log(string logMessage);
    }
}
Class: Logger
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace Strategy
{
    public class Logger
    {
        private ILogHandler _LogHandler;

        public void SetLogHandler(ILogHandler logHandler)
        {
            _LogHandler = logHandler;
        }

        public void Log(string logMessage)
        {
            if (_LogHandler != null)
            {
                _LogHandler.Log(logMessage);
            }
        }
    }
}
When we implement the Logger class in this way than it is according to the Open Closed Principle. We could provide any implementation of the ILogHandler without the need to make any modifications to the class. For example:
Class: ConsoleLogger : ILogHandler
1
2
3
4
5
6
7
8
9
10
namespace Strategy
{
    public class ConsoleLogger : ILogHandler
    {
        public void Log(string logMessage)
        {
            Console.WriteLine(logMessage);
        }
    }
}
Class: FileLogger : ILogHandler
1
2
3
4
5
6
7
8
9
10
namespace Strategy
{
    public class FileLogger : ILogHandler
    {
        public void Log(string logMessage)
        {
            // Log to file functionality
        }
    }
}
I hope you found these examples helpful. Also take a look at the following links:

http://www.dofactory.com/Patterns/PatternStrategy.aspx
http://patnys.com/archive/2008/04/15/strategy-pattern.aspx