Jonathan Birkholz

Structure Map 2.6 Constructor Arguments

Constructor Injection

When we use an IoC tool the most basic functionality we expect is to have constructor injection. That means if we have a type we are resolving and one of the constructor’s parameters is also a type, the container will resolve that type as well.

And turtles all the way down…

If we have two types(Foo : IFoo and Bar : IBar) and in Bar’s constructor it has an IFoo parameter, we should expect the IFoo parameter to be resolved to an instance of Foo.

1
2
3
4
5
6
7
8
9
class Bar : IBar
{
public Bar(IFoo foo)
{
Foo = foo;
}
public IFoo Foo { get; set; }
}

Our container is setup like :

1
2
3
4
5
6
7
_container = new Container();
_container.Configure(x =>
{
x.For<IFoo>().Use<Foo>();
x.For<IBar>().Use<Bar>();
});

We then expect :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Test]
public void IBar_should_resolve_to_Bar()
{
var bar = _container.GetInstance<IBar>();
bar.ShouldBeType<Bar>();
}
[Test]
public void IBars_IFoo_dependency_should_resolve_to_Foo()
{
var bar = _container.GetInstance<IBar>();
bar.Foo.ShouldBeType<Foo>();
}

Constructor Arguments

Sometimes you need to specify the exact argument for a given type when it is constructed. Structure Map allows you to provide specific values for resolving a constructors argument.

For example, Ryan was asking if there is a method with SM to resolve an “id” value from an HttpContext. I know SM has some fancy session management lifecycle features built in, but since I don’t live in the Web world I have never explored what can and can not be done with those features.

What I do know is that I can specify where my “id” parameter comes from.

Let’s look at this simple example.

In my scenario I have a Foo class.

1
2
3
4
5
6
7
8
9
10
11
class Foo : IFoo
{
public Foo(int id, IBar bar)
{
Id = id;
Bar = bar;
}
public int Id { get; set; }
public IBar Bar { get; set; }
}

The id that is passed into Foo is providing by some mysterious X. In my case my X is an IIdProvider.

1
2
3
4
5
6
7
class IdProvider : IIdProvider
{
public int GetId()
{
return 1;
}
}

Now I want to tell SM that when it resolves an IFoo, I want it to use the IIdProvider to get the “id”.

1
2
3
x.For<IFoo>().Use<Foo>()
.Ctor<int>("id")
.Is(c => c.GetInstance<IIdProvider>().GetId());

All together the configuration is:

1
2
3
4
5
6
7
8
9
_container = new Container();
_container.Configure(x =>
{
x.For<IIdProvider>().Use<IdProvider>();
x.For<IBar>().Use<Bar>();
x.For<IFoo>().Use<Foo>()
.Ctor<int>("id")
.Is(c => c.GetInstance<IIdProvider>().GetId());
});

And my tests to verify it works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Test]
public void should_resolve_Bar()
{
var foo = _container.GetInstance<IFoo>();
foo.Bar.ShouldBeType<Bar>();
}
[Test]
public void should_resolve_id()
{
var foo = _container.GetInstance<IFoo>();
foo.Id.ShouldBe(1);
}

Lazy Constructor Arguments

Then Ryan tells me, he would really like to be lazy because he might not need the id for all requests. There are some Lazy features added to SM 2.6 but let’s just use what we already know to solve this problem.

Instead of having an int Id parameter, let’s have a Func getId parameter.

Foo changes to :

1
2
3
4
5
6
7
8
9
10
11
class Foo : IFoo
{
public Foo(Func<int> getId, IBar bar)
{
GetId = getId;
Bar = bar;
}
public Func<int> GetId { get; set; }
public IBar Bar { get; set; }
}

Now our constructor configuration changes to :

1
2
3
x.For<IFoo>().Use<Foo>()
.Ctor<Func<int>>("getId")
.Is(c => c.GetInstance<IIdProvider>().GetId);

And our tests become :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Test]
public void should_resolve_Bar()
{
var foo = _container.GetInstance<IFoo>();
foo.Bar.ShouldBeType<Bar>();
}
[Test]
public void should_resolve_id()
{
var foo = _container.GetInstance<IFoo>();
foo.GetId().ShouldBe(1);
}

Yes it is a poor man’s lazy instantiation. But in many ways its the clearest way to have the functionality.

You can find all this code in my Git Hub Learning Repository and the Learning Structure Map solution : http://github.com/RookieOne/Learning

Wizards of Smart - Episode 3 Testing

Ryan and I talk a bit about testing, TDD, code coverage, code quality, Dependency Injection…. so a bunch of random topics loosely related to testing.

Structure Map 2.6 Using Conventions

An awesome feature of StructureMap is the ability to scan assemblies and register types using different conventions. At first this might seem a trivial feature but I had a project in the past where this approach was shunned upon. Even when I tried to bring in this functionality it was not approved. The result? A ‘module’ class with tons of namespaces and tons of register lines. Why suffer that pain?!

Default Convention

How many times do we have an IFoo interface and then the concrete implementation named Foo. Shouldn’t our IoC container be smart enough to recognized this most basic and popular pattern? Well StructureMap is that smart.

To use conventions, we first specify which assemblies we want to scan. Then we add conventions to use when scanning those assemblies. So to use the default convention scanner we simply do:

1
2
3
4
5
6
container.Configure(x => x.Scan(s =>
{
s.TheCallingAssembly();
s.Convention<DefaultConventionScanner>();
} ));

And naturally we should have a test to verify it works as we expect.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[Test]
public void should_load_IFoo()
{
var container = new Container();
container.Configure(x => x.Scan(s =>
{
s.TheCallingAssembly();
s.Convention<DefaultConventionScanner>();
} ));
// IFoo -> Foo
// IWhatever -> Whatever
var foo = container.GetInstance<IFoo>();
foo.ShouldBeType<Foo>();
}

Add All Types

Sometimes we have more than one implementation of a given interface. For that scenario we can use the same scanning process but this time tell the scanner to add of types of a given interface.

1
s.AddAllTypesOf<IEntity>()

What’s even cooler is that we can add additional information to the registration. For example, what if we want to register all our IEntity types but use the actual type name as a key (PersonEntity –> ‘Person’). Easy peasy.

s.AddAllTypesOf().NameBy(t => t.Name.Replace(“Entity”, “”)); And our test?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Test]
public void should_load_Person_Entity()
{
var container = new Container();
container.Configure(x => x.Scan(s =>
{
s.TheCallingAssembly();
s.AddAllTypesOf<IEntity>().NameBy(t => t.Name.Replace("Entity", ""));
}));
var person = container.GetInstance<IEntity>("Person");
person.ShouldBeType<PersonEntity>();
}

Custom Convention

Beyond the built in Default Convention and the ability to add all types, we can create our own custom conventions. These used to be called TypeScanners, but are now implementations of the IRegistrationConvention interface. I think the renaming was a good idea. I always had a hard time naming my scanners because I kept calling them conventions. Now I don’t have that problem anymore. :)

The interface is simple and has only one method you need to implement called Process.

1
2
3
4
5
6
7
public class CustomConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
throw new NotImplementedException();
}
}

For our custom convention we are going to register all types of IController and use the type name as the key. So this is similar to how we registered our IEntity but instead of using the AddAllTypes feature we are using a convention.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ControllerConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (!type.CanBeCastTo(typeof (IController)))
return;
string name = GetName(type);
registry.AddType(typeof (IController), type, name);
}
static string GetName(Type type)
{
return type.Name.Replace("Controller", "");
}
}

And then to use our new conventions we just need to do:

1
2
3
4
5
6
7
_container = new Container();
_container.Configure(x => x.Scan(s =>
{
s.TheCallingAssembly();
s.Convention<ControllerConvention>();
}));

Here are the tests:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Test]
public void should_use_register_a_single_controller()
{
var count = _container.GetAllInstances<IController>().Count;
count.ShouldBe(1);
}
[Test]
public void should_register_controller_for_person()
{
var controller = _container.GetInstance<IController>("Person");
controller.ShouldBeType<PersonController>();
}

Here we just covered the basics of using conventions and the assembly scanner with StructureMap to reduce wasteful registration code.

The code can be found in my learning solution on GitHub : http://github.com/RookieOne/Learning

Structure Map Basics 2.6

I’ve had doing Structure Map posts on my To-Do list for a long time now. It is time to spring clean these items and get some posts up!

Like my other learning posts / projects, you can find the code at : http://github.com/RookieOne/Learning

I don’t want to dive into how / why you can use a DI / IOC tool like StructureMap. Or why SM over another IoC tool. So I won’t. :)

My recommendation is prefer to use a tool made by people who think about the problem the same way you do. You will be happier and self-discover features more easily.

I like the way Jeremy Miller thinks and naturally love Structure Map.

Normal Registration

Previously to register an interface with a concrete type there was a fluent by extremely verbose interface. With 2.6 that has been greatly simplified for a For().Use() syntax.

1
2
3
4
5
6
7
8
9
10
[Test]
public void IFoo_should_resolve_to_Foo()
{
var container = new Container();
container.Configure(x => x.For<IFoo>().Use<Foo>());
var foo = container.GetInstance<IFoo>();
foo.ShouldBeType<Foo>();
}

Singleton Registration

To register the type as a singleton, we just need to add a Singleton() call between our For and Use calls.

1
2
3
4
5
6
7
8
9
10
11
[Test]
public void should_return_same_instance_of_Foo()
{
var container = new Container();
container.Configure(x => x.For<IFoo>().Singleton().Use<Foo>());
var foo1 = container.GetInstance<IFoo>();
var foo2 = container.GetInstance<IFoo>();
foo1.ShouldBeTheSameInstanceAs(foo2);
}

Open Generic Registration

One of the cool things with StructureMap is the ability to register open generics. I know other tools support this, but it is still cool. So in this test I am registering an open generic interface IRepository<> with a concrete yet still open generic implementation Repository<>. I can then asked for a IRepository and I get back a Repository.

1
2
3
4
5
6
7
8
9
10
[Test]
public void IRepositoryT_should_resolve_to_RepositoryT()
{
var container = new Container();
container.Configure(x => x.For(typeof (IRepository<>)).Use(typeof (Repository<>)));
var repository = container.GetInstance<IRepository<Book>>();
repository.ShouldBeType<Repository<Book>>();
}

Open Generic with Closed Generic Alternative

Now this is where things get real cool. Besides registering an open generic concrete implementation, I can also registered a closed generic alternative. So in my test I am registering Repository<> for all IRepository<>. But I am also registering CustomerRepository with IRepository.

So with this I can have a general implementation but then provide specific implementations for those exceptional cases.

1
2
3
4
5
6
_container = new Container();
_container.Configure(x =>
{
x.For(typeof (IRepository<>)).Use(typeof (Repository<>));
x.For<IRepository<Customer>>().Use<CustomerRepository>();
});

Now for the tests pay close attention to the request to the container. Notice how the user of the container doesn’t need to know if the implementation they are using is the generic or the specific alternative. Isn’t that sweet!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Test]
public void IRepository_book_should_resolve_to_Repository_book()
{
var repository = _container.GetInstance<IRepository<Book>>();
repository.ShouldBeType<Repository<Book>>();
}
[Test]
public void IRepository_customer_should_resolve_to_Customer_Repository()
{
var repository = _container.GetInstance<IRepository<Customer>>();
repository.ShouldBeType<CustomerRepository>();
}

Naturally there are tons of other things Structure Map does but this was just a brief intro to some of the basics. I plan on blogging a bit more on some of the other neat features that make SM my IoC tool of choice.

Virtual Brown Bag Summary 5/20/10

We had another great turnout today so a big thanks to everyone who attended. And although I didn’t get to share my ‘Monad’, Claudio mentioned monad. My goal now is to mention monad with every show. Mission Accomplished.

Dynamics

Today Claudio did a great demo on some of the dynamic features with .Net 4. He recently gave a dynamics presentation at the Visual Studio 2010 Launch Event in Dallas.

Claudio did a blog post on his blog which can be read here : http://claudiolassala.spaces.live.com/blog/cns!E2A4B22308B39CD2!3110.entry

I plan on getting the material and integrating that with my Learning CSharp project on GitHub.

Claudio talked through using the dynamic keyword, Expando object, and your own DynamicObject implementation. He also did it with learning tests which is awesome.

Wizards of Smart Podcast I also talked a bit about the Wizards of Smart podcast Ryan and I started last week. Episodes 1 and 2 are out. I covered a bit on what tools / apps / websites we are using to make the podcast.

Episode 1 can be found here : http://www.theabsentmindedcoder.com/2010/05/wizards-of-smart-podcast-episode-1.html

Episode 2 can be found here : http://www.theabsentmindedcoder.com/2010/05/wizards-of-smart-podcast-episode-2.html

The blog post about the tools can be found here : http://www.theabsentmindedcoder.com/2010/05/tools-of-our-podcasting.html

I plan on doing a post on my switch from WavePad to Mixcraft which Claudio and I talked about.

Mixcraft can be found here : http://www.acoustica.com/mixcraft/

Greg Young Webcasts

George brought up the news that Greg Young will be offering free webcasts in the summer. Greg Young is the genius behind CQRS and is a leading voice in DDD.

For more info on Greg Young check out one of my favorite podcasts ever : Our Grand Failure - http://herdingcode.com/?p=189

He also blogs at codebetter.com : http://codebetter.com/blogs/gregyoung/default.aspx

His post on the webcasts can be read at http://codebetter.com/blogs/gregyoung/archive/2010/05/19/webcasts.aspx

Community for FSharp Meeting + Bistro

Ryan held another Community for FSharp (http://www.communityforfsharp.net/) meeting this week. This week was a chance for people to share what they are working on with F#.

Chris Marinos shared F# Koans.

And what I shared at the VBB was the incredibly interesting Bistro framework.

Bistro is an MVC implementation in F# (basically) For more info check out : http://bistroframework.org/index.php?title=FSharp

C# Sig Presentation - Evolve Your Code

I gave this presentation back in March but I forgot to blog about it!

So here is the quick run down.

Evolve Your Code was a presentation I gave first at Houston Techfest.

The abstract is:

Fluent NHibernate, HTML Helper & Input Builders, and Automapper (and others) use extension methods, fluent interfaces, and expressions to make a more approachable, readable, and flexible coding framework. These tools aren’t restricted to the elite third party frameworks. You too can use these techniques to evolve your code.

But really the abstract should be:

Learn how to use extension methods, lambdas, expressions, and fluent interfaces to make more approachable, readable, and flexible code. We will learn the basics of these .Net 3.5 features along with applying the features to implement design patterns.

The code and slide show can be found at : http://github.com/RookieOne/Evolve-Your-Code

There were some issues with opening the solution file. The problem is that the Visual Studio selector can figure out what version to open. If you open the solution file from Visual Studio, there isn’t any problems.

Wizards of Smart Podcast - Episode 2

Episode 2 is thrown together bits of conversation Ryan and I had after the recording of Episode 1. Based on recommendations from Claudio Lassala and Ben Scheirman I balanced the L/R (or at least tried to). I also added an intro. I realized afterwards I need an outro so expect that change for Episode 3.

I think the best part of the conversation comes towards the end of the podcast but I would like to hear from any / all listeners.

I was thinking Ryan and I should target smaller podcasts. Instead of a 40 min – hour podcast, we should just have more, smaller podcasts. What do you think?

Anyway, enjoy the podcast.

The Tools of Our Podcasting

One might ask, How are we creating this podcast? And that would be a good question.

Ryan is in Bellingham, Washington and I am in Katy, Texas. So we started our research on how we can record ourselves by examining different Skype add-ins.

On Monday we spent 2 hours trying different add-ins and configurations. We finally settled on using CallGraph http://callgraph.biz/

After we recorded our conversation, I went about looking for different sound editing software. I ran across WavePad and I could immediately become productive.

WavePad is made by NCH Software and can be found @ http://www.nch.com.au/wavepad/index.html

After I had an edited down version of the conversation, I looked for a place to host the podcast. What I settled on for now is using PodBean.

PodBean allows for some free hosting services. Find out more information @ http://www.podbean.com/

I can then host the podcast at PodBean and then provide a little player on this site.

Wizards of Smart Podcast - Episode 1

Ryan Riley and I had talked about doing a podcast for years now. We tend to have great conversations (well we think they are great :) ) about technology and programming. The only issue we had was that afterwards there was no record of the conversation. Well we finally hit the record button and started our own podcast. Since we are developers we approach everything from an iterative process. This is a rough cut of the first episode. We will continue to work at the process and make each episode better than the one before.

Both of us enjoyed doing the podcast and look forward to doing more in the future.

Actually the conversation went on longer than this and is being molded into the second episode which I will post once its done.

Let us know what you think!

Virtual Brown Bag 5/13/2010

I am going to try and do a better job capturing what we talk about and blog the notes the day of the VBB.

We started the VBB off with me doing a walkthrough of some of the learning tests and blog posts surrounding MongoDB and NoRM.

My blog posts can be found here:

Learning Mongo DB and NoRM : http://www.theabsentmindedcoder.com/2010/05/learning-mongo-db-and-norm.html Basic NoRM Ids : http://www.theabsentmindedcoder.com/2010/05/basic-norm-ids.html And you can get all the code in my learning git hub repository found @ http://github.com/RookieOne/Learning

Azam from High On Coding shared via chat his learning project called SKOOL. It combines MongoDB and MVC and can be found @ http://github.com/azamsharp/SKOOL

Azam wanted to communicate that it is in the very early stages.

George Mauer shared some NHibernate Internals focusing on the AbstractEntityPersister. George also shared some of the Dynamic Property support built into NHibernate.

Chad (sorry I forgot to write down his last name) showed off his first experiments with Moles. Moles is an Isolation framework for .Net provided by Microsoft Research.

Learn more at http://research.microsoft.com/en-us/projects/moles/

And at the end I briefly shared my Extension Methods post : http://www.theabsentmindedcoder.com/2010/05/using-extension-methods-to-remove.html

Claudio promised to share some of his dynamic goodness that he is presenting at Dallas this week.

As for me, I will continue to do my thing and share whatever is on my mind.