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

No comments: