Wednesday, December 14, 2005

ObjectBuilder

Updated 1/14/2006 to include definition of MyBuilderContext class

I've started to play with ObjectBuilder (OB) that comes with CAB and EntLib to learn how it works. I’m no expert so take what I’m about to say in that context. What I’m doing is looking at the unit test to figure out how it works. You could also take a look at the CAB and EntLib 2.0 code to get an idea as well. I create a simple sample to get my feet wet. Again I did this as a first try at understanding OB and the code presented here has been stripped down to present the idea. The important things to note is that OB is a framework for building a DI system, so you have to write some code to the DI system in place. In this example the DI sub-system (the poor mans version) is implemented in the MyContextFactory. Also note that my sample does not dispose of the object by running through the build strategy at the end… this is my laziness.

This is the main program file. I want to create an instance of MyForm as a singleton without using new and also inject the necessary object needed by MyForm. In this example I also wanted to test constructor injection, method injection and property injection. Method injection is a very interesting idea fro doing initialization after construction… neat.

Program.cs


using System;
using System.Collections.Generic;
using System.Windows.Forms;


namespace ObjectBuilderApp
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

MyForm form = MyBuilderFactory<MyForm>.BuildSingletonObject( "Main Form" );
Application.Run(form);
}
}
}


This is the MyForm class that represents the form. Note I did not show the designer code here. It requires a number of object that are injected.

MyForm.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.ObjectBuilder;

namespace ObjectBuilderApp
{
public partial class MyForm : Form
{
private Customer _customer;
private Foo _foo;

// Constructor Injection
[InjectionConstructor()]
public MyForm(Customer customer) : this()
{
this._customer = customer;
}


// Setter Injection
[Dependency( SearchMode = SearchMode.Local, CreateType = typeof(Foo), NotPresentBehavior = NotPresentBehavior.CreateNew)]
public Foo Foo
{
set
{
this._foo = value;
}
}

// Method Injection
[InjectionMethod()]
public void Display([Dependency(CreateType = typeof(Foo), NotPresentBehavior = NotPresentBehavior.CreateNew)] Foo foo)
{
System.Diagnostics.Trace.WriteLine(foo.Name);
}

[InjectionMethod()]
public void Display2([Dependency(CreateType = typeof(Foo), NotPresentBehavior = NotPresentBehavior.CreateNew)] Foo foo)
{
System.Diagnostics.Trace.WriteLine(foo.Name);
}

[InjectionMethod()]
public void Display3([Dependency(CreateType = typeof(Foo), NotPresentBehavior = NotPresentBehavior.CreateNew)] Foo foo)
{
System.Diagnostics.Trace.WriteLine(foo.Name);
}

public MyForm()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(this._customer._foo.Name);
}
}
}


This is the MyContextFactory class. This is a static class that allows for the creation of an object based on the Object Builder (OB) framework. In some ways this class is my DI subsystem (yes not a very good version).

MyContextFactory.cs

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.ObjectBuilder;

namespace ObjectBuilderApp
{
public class MyBuilderFactory<T> where T : class
{
public static T BuildSingletonObject( string name )
{
MyBuilderContext ctx = new MyBuilderContext();

//ctx.InnerChain.Add(new SingletonStrategy());
ctx.InnerChain.Add(new CreationStrategy());

// enables method injection
ctx.InnerChain.Add(new MethodReflectionStrategy());
ctx.InnerChain.Add(new MethodExecutionStrategy());

// enables property njection
ctx.InnerChain.Add(new PropertyReflectionStrategy());
ctx.InnerChain.Add(new PropertySetterStrategy());

ctx.Policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy());

ctx.Policies.Set<ISingletonPolicy>(new SingletonPolicy(true), typeof(MyForm), null);

return ctx.HeadOfChain.BuildUp(ctx, typeof(T), null, name) as T;
}
}
}



This Customer class is the Customer class that gets injected into the MyForm class, but itself also needs another object Foo to be injected.

Customer.cs

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.ObjectBuilder;
using System.Windows.Forms;

namespace ObjectBuilderApp
{
public class Customer
{
public Foo _foo;

// Constructor Injection
[InjectionConstructor]
public Customer([CreateNew] Foo foo)
{
this._foo = foo;
}

// Method Injection
[InjectionMethod]
public void Display([Dependency(Name="MyFoo", CreateType = typeof(Foo), NotPresentBehavior = NotPresentBehavior.CreateNew)] Foo foo)
{
System.Diagnostics.Trace.WriteLine(foo.Name);
}
}
}



The Foo class is just a nother class that gets used by the Customer class. This class does not use any kind of injection.

Foo.cs
using System;

using System.Collections.Generic;
using System.Text;

namespace ObjectBuilderApp
{
public class Foo
{
string _name;

public string Name
{
get
{
if (this._name == null)
return "Norm";
else
return this._name;
}
set
{
this._name = value;
}
}
}
}



MyBuilderContext.cs

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.ObjectBuilder;

namespace ObjectBuilderApp
{
public class MyBuilderContext : BuilderContext
{
public IReadWriteLocator InnerLocator;
public BuilderStrategyChain InnerChain = new BuilderStrategyChain();
public PolicyList InnerPolicies = new PolicyList();
public LifetimeContainer lifetimeContainer = new LifetimeContainer();

public MyBuilderContext()
: this(new Locator())
{
}

public MyBuilderContext(IReadWriteLocator locator)
{
InnerLocator = locator;
SetLocator(InnerLocator);
StrategyChain = InnerChain;
SetPolicies(InnerPolicies);

if (!Locator.Contains(typeof(ILifetimeContainer)))
Locator.Add(typeof(ILifetimeContainer), lifetimeContainer);
}
}
}



5 Comments:

At 7:32 AM, Anonymous Anonymous said...

Hi Norman,

I have not found the myBuilderContext class in your blog post. The following code snippet does work fine for me:

public class MyBuilder : BuilderBase<BuilderStage>
{
public MyBuilder()
{
Strategies.AddNew<SingletonStrategy>(BuilderStage.PreCreation);
Strategies.AddNew<ConstructorReflectionStrategy>(BuilderStage.PreCreation);
Strategies.AddNew<PropertyReflectionStrategy>(BuilderStage.PreCreation);
Strategies.AddNew<MethodReflectionStrategy>(BuilderStage.PreCreation);
Strategies.AddNew<CreationStrategy>(BuilderStage.Creation);
Strategies.AddNew<PropertySetterStrategy>(BuilderStage.Initialization);
Strategies.AddNew<MethodExecutionStrategy>(BuilderStage.Initialization);
Strategies.AddNew<BuilderAwareStrategy>(BuilderStage.PostInitialization);

Policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy());
sb.Policies.Set<ISingletonPolicy>(new SingletonPolicy(true), typeof(Form1), null);
}

}

public class MyBuilderFactory<T> where T : class
{
public static T BuildSingletonObject(string name)
{
// use default builder to spare code
//Builder sb = new Builder();
MyBuilder sb = new MyBuilder();

return sb.BuildUp<T>(new Locator(),name,null);
}
}

Yours,

Alois Kraus

 
At 12:33 AM, Blogger Norman Headlam said...

Indeed I did not post the MyBuilderContext class. I will do so shortly. Thanks.

 
At 8:46 PM, Anonymous Anonymous said...

Great work -- this looks like exactly what I need to ramp up. I can't quite get it all to build, however (the code posted by Alois has a bit of scope weirdness with sb and Form1).

Do you have the full example that you could post? That would be cool.

 
At 3:21 PM, Anonymous Anonymous said...

great work, i was looking for a sample of how to use OB, yor simple post is very helpfull!


i've found a adjust to be made at
MyBuilderFactory.cs

FROM:
ctx.Policies.Set<ISingletonPolicy>(new SingletonPolicy(true), typeof(MyForm), null);

TO:
ctx.Policies.Set<ISingletonPolicy>(new SingletonPolicy(true), typeof(T), null);


thanks!

// and sorry about my english...

 
At 7:54 AM, Anonymous Anonymous said...

Who knows where to download XRumer 5.0 Palladium?
Help, please. All recommend this program to effectively advertise on the Internet, this is the best program!

 

Post a Comment

<< Home