Software Mechanics
Why do we even have that lever?

Entlib 5.0 Hands-on labs released

May 25, 2010 06:53 by chris

At long last, our final core deliverable for Enterprise Library 5.0 is released - the Hands-on labs. This set of labs (in either VB or C#, your choice) walks you through the various features of each of the blocks. It's a great way to learn what Entlib can do for you, and gives examples of just about everything you can do.

It's available for download here.

And that's it, I'm going back to bed. :-)


Currently rated 1.5 by 802 people

  • Currently 1.521197/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: .NET | Entlib | p&p | Unity
Actions: E-mail | Permalink | Comments (1) | Comment RSSRSS comment feed

Catching up with recent stuff

May 1, 2010 15:39 by chris

Wow, get a little behind and how time flies. Sorry for the delays, folks, I’ve had some personal issues which kept me from updating this blog when I really should have.

So, in no particular order:

  • Enterprise Library 5.0 has been released! Grigori has the full release announcement, along with download links. The doc set is going through the final, final, FINAL edit passes right now, and hopefully should be out early next week. Once we get the docs out, the final standalone Unity 2.0 installer will release as well. In the meantime, if you want the Unity 2.0 bits, they’re included in the Entlib 5.0 bin directory. And yes, we know the MSDN landing page still points to Entlib 4.1 – MSDN is doing some kind of database migration (I neither know nor want to know the details) which have rendered our landing pages read-only until they’re done. The update is ready to go but until their system is updated we’re stuck with the old one.
  • As part of the Entlib 5.0 release, I did an interview with the Pluralcast about Entlib. I don’t think I made too much of a fool of myself. :-)
  • I did two presentations at the recent Seattle Code Camp. One was, to be honest, a flop, but the other one, titled “Abusing Lambdas for Fun and Profit” was quite well received. I’ve had several requests for the source code to that presentation, so I’ve put the slides and code up on my download page. Enjoy!

I guess that’s it for the moment. Have fun, and be sure to let the team know what you think of Entlib 5!


Currently rated 1.6 by 47 people

  • Currently 1.638295/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: .NET | Entlib | p&p | Unity | Personal
Actions: E-mail | Permalink | Comments (2) | Comment RSSRSS comment feed

Unity 2.0 Automatic Factories

January 7, 2010 18:25 by chris

As we’re sloping down the glide path into the release of Unity 2.0 and Entlib 5, I wanted to start talking about some of the things that got added or changed in the container. For this post I want to discuss the new “automatic factories feature.”

This one was a recent addition that I threw in over the Christmas holiday, “inspired” by a feature recently added to AutoFac. At it’s core it answers a simple problem: what if I have to create objects through the container, but I don’t need them at injection time, but later?

This comes up in lots of situations. The object may be heavy, so you don’t want to create it until you absolutely need it. Or you need many of them, but can’t predict when.With Unity 1.2, you basically had two choices in this scenario.

First, you could inject the container as a dependency. This works, but has several issues. You’ve now coupled yourself to the container. Also, you have no way of knowing as a consumer of that class what needs to be in the container – the dependencies have become completely opaque.

A second choice is to inject a factory object. Then call the factory when you need to create an object; the factory implementation can call back into the container. This improves testability and solves the lack of metadata problem above. However, it has the downside of lots of boilerplate code. A separate factory class for every class in your system. Ugh.

Automatic factories solve these problems pretty easily. It’s so simple I should have done it a long time ago. Simply have a dependency of type Func<Whatever>. Then you’ll get that delegate injected. When you invoke the delegate, it calls back into the container to Resolve<Whatever>().

If you resolve the dependency with a name, that’s the name the func will use when invoked to do a resolve.

Finally, if your dependency is Func<IEnumerable<Whatever>>, then you’ll get a ResolveAll call executed.

Simple. straightforward, and solves all the problems of coupling, lack of metadata, and boilerplate code.

This is in the drop I just posted yesterday on Codeplex source control – go take a look and let me know what you think!


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: .NET | p&p | Unity
Actions: E-mail | Permalink | Comments (3) | Comment RSSRSS comment feed

A new article in MSDN (well, kind of…)

November 5, 2009 14:25 by chris

MSDN magazine has just published my latest article. It’s part of the Inside Microsoft patterns & practices online column, and it’s about building libraries that take advantage of dependency injection. I used the work we did rearchitecting Enterprise Library 5 as a sort of case study of the goals, forces, and resolutions. I’m actually quite proud of what we did here, and thought that others might be interested.

Unfortunately, for those of you who get the printed magazine, you may see my name on the cover, but the description of the article is actually from Brian Randell’s article from October’s issue.  I will be having … words … with the magazine staff over this one tomorrow. Sorry Brian, TFS work items are something I’m very happy to let you be the expert in.

Anyway, if you’re interested in how Entlib 5 works under the hood, or want to write a library that uses a DI container without forcing your users to use a specific container, please check it out. And let me know what you think!


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: p&p | Unity | Entlib | .NET
Actions: E-mail | Permalink | Comments (1) | Comment RSSRSS comment feed

Updating the Wiki sample to MVC RC1

February 16, 2009 10:10 by Chris

The recently released ASP.NET MVC Release Candidate broke a couple things in my Wiki sample I originally built for MSDN magazine. So, I've updated them again. Major changes:

  • Updated the ModelBinder implementation to match the new semantics
  • Using the global model binder registration instead of the attributes on the action method (although to be honest there's no really good reason for this)
  • No more view codebehind files

At this point, the sample runs, but it's showing it's pedigree as code that's come up from the original CTP's through beta. So after the final release, I'll do one more refresh on this project, and rebuild it from scratch using the final project templates and the latest MVC stuff. I don't expect a whole lot of change in the controllers, and none in the domain model. But the views I expect will change significantly. Hopefully I can grab one of the new themes from the MVC design gallery so folks don't need to keep looking at my ugly lack of CSS skills. ;-)

I've put a permanent home for this sample on my blog at this page: http://www.tavaresstudios.com/Blog/page/ASPNET-MVC-Wiki-Sample.aspx. Go there for download instructions.

Have fun!


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: .NET | Unity | MVC
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Resolving a Singleton? Here's how...

January 23, 2009 18:01 by chris

A user posted a question on the Unity Codeplex forum a couple of days ago. He wanted to configure Unity through the configuration file to resolve a singleton object. My first thought was "of course, that's easy". Then I read the actual question and it got a bit more interesting. I thought I'd put my response here instead of the forum because I thought it was an interesting discussion, and I'd like it to still be around the next time it came up.

The thing was, the object in question was an actual singleton, along these lines:

public class MySingleton : IMySingleton { 
    private MySingleton() { }
    public static MySingleton Instance { 
        get { return instance; } 
    } 
    private static MySingleton instance = new MySingleton(); 
} 

He wanted to configure Unity to, essentially, return the Instance property of this singleton class during resolution. That's not so easy.

So, how do you fit something like this into the container? You could write an extension or custom config node to special case it, but that's just asking for trouble. Plus, it encourages use of singletons, which are pretty well understood to be Not A Good Thing these days.

Unfortunately, many times the singleton behavior is forced upon you by libraries or frameworks. Or you may have lots of other code that isn't using a container that you want to leave unchanged. So what do you do?

Luckily in this case, the singleton has an interface on it. So what I'd do is start by creating a new class that has a public constructor, implements the singleton interface, and defers all the methods to the underlying singleton.

public class MySingletonWrapper : IMySingleton {
    public void MyMethod() {
        return MySingleton.Instance.MyMethod(); 
    }
}

Something along those lines.

Next, I'd configure the container to inject the wrapper when asked to resolve IMySingleton. The nice thing about this is that you get simple integration with the code you currently have, and your new classes which you build up through the container are ignorant of both the singleton class and the wrapper; they just use the interface.

You could stop there. That's the nice thing about proper refactoring: at each step you could stop and still leave your system in a working state. But why? Why not get rid of the singleton and let the container manage the object instances? This is pretty easy through more refactorings.

The first thing to do is change the type of the Instance property on the singleton to return the interface type rather than the concrete type. This should be pretty transparent to the callers, and your compiler will tell you if any edits are required.

The next step is to move the guts of the interface implementation out of the MySingletonClass and into the MySingletonWrapper class. Then change the instance the singleton manages to an instance of MySingletonWrapper instead. Finally, change the methods on the interface to delegate to the wrapper instance instead.

public class MySingletonWrapper : IMySingleton
{
    public void MyMethod() {
        DoStuffHere();
    }
}

public class MySingleton : IMySingleton
{
    public IMySingleton Instance {
        get { return instance; }
    }

    private static IMySingleton instance = new MySingletonWrapper();

    // interface implementation now delegates to instance
    public void MyMethod() {
        instance.MyMethod();
    }
}

At this point, all your code should still be running, through the container or not. You should definately change the name of MySingletonWrapper to something a lot more descriptive at this point. That'll be very easy since the only places that use this class name are your container configuration and the MySingleton class.

From here, the next thing I'd probably do is remove the interface implementation from the MySingleton class. This class now has only one responsibility: managing the lifetime of that inner instance.

Now, as you go forward, you should be able to remove references to the explicit singleton and replace them with objects injected from the container. Over time, you should be able to remove all the reference to MySingleton without affecting your code's behavior at all. When the last reference is gone, you delete the singleton class.

And that's how I'd resolve a singleton.


Currently rated 1.6 by 28 people

  • Currently 1.571429/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: .NET | Agile | Unity
Actions: E-mail | Permalink | Comments (3) | Comment RSSRSS comment feed

Elegant Code Cast

January 23, 2009 17:01 by Chris

(Whew, I didn't realize I'd gotten so far of the blogging wagon. Time to hop back on!)

At the last Seattle Code Camp, I ended up talking with David Starr for quite a while. He apparently thought I knew what I was talking about (shh! Don't tell him the truth!) and invited me to be a guest on the Elegant Code Cast. It was a great talk about EntLib, life in p&p, Unity, and all sorts of other stuff.

The episode is available here. Thanks again, guys for the great chat!


Currently rated 1.5 by 47 people

  • Currently 1.468085/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: .NET | Entlib | p&p | Silverlight | Unity
Actions: E-mail | Permalink | Comments (2) | Comment RSSRSS comment feed

Announcing Unity 1.2 for Silverlight

December 11, 2008 11:10 by Chris

A little early Christmas present for everyone. ;-)

 

What's in it?

The installer includes the binary, the docs, and a new Silverlight version of our Stoplight quickstart (and no, I didn't port the event broker, anyone want to give it a shot?)

What's different?

Probably the biggest difference is that Microsoft.Practices.Unity.dll for Silverlight is contained in a single assembly. We've merged the previous ObjectBuilder2, Unity, and StaticFactoryExtension into the one DLL. This resulted in a slightly smaller overall package and a lot more convenience when referencing the container, since you don't have to hunt for multiple DLLs when adding references.

One thing that's not included is the XML configuration assembly, Microsoft.Practices.Unity.Configuration.dll. There's a simple reason for that - Silverlight doesn't support System.Configuration. We'll have to come up with a new configuration file story. I'm toying with some XAML based ideas on this front, but it'll be a while.

Also, the recently released interception mechanism (Microsoft.Practices.Unity.Interception.dll) hasn't yet been ported, so that's not included either. We'd like to include it going forward, but it'll take some work to it working and we didn't want to delay the release.

The container basically performs the same in Silverlight as it does on the Desktop CLR. The container API is identical. There is one minor gotcha: due to the difference in security model in Silverlight, you can only resolve public types through the container. The desktop version lets you do public or internal.

How'd we do it?

Luckily, the Silverlight environment really is very close to the Desktop CLR. It was mainly a case of pulling out references to things that Silverlight didn't support. We'd already started down this road with some work done in version 1.2. Replacing calls to methods that didn't exist on Silverlight with ones that did, for example. I did have to tweak a couple of source files (for things we missed) but it didn't affect the overall code any.

In order to do the port, I started by creating an empty Silverlight project. I then imported the Unity source files into it, and then let the compiler tell me what stuff didn't work. Yes, I'm lazy that way.

The vast majority of the code works for both desktop CLR and Silverlight. There were a couple cases where we needed environment-specific code. Looking at the source, you'll see a few files with the .Desktop.cs or .Silverlight.cs extensions. These are how we marked up the code that was specific to one platform or the other. The .Silverlight.cs files are only included in the silverlight project, and the .Desktop ones are specific to the desktop project. For classes that needed to be tweaked, I used partial classes, with the partial parts in a platform-specific file. The various custom exceptions are probably the biggest example of this. On the Desktop CLR, exceptions should have a serialization constructor and be serializable. Silverlight doesn't support this. So each exception class is a partial class. The serialization details are in a .Desktop.cs file. The Silverlight project simply omits those files and we're good.

The unit test suite has also been ported, and uses the same approach. Not every test from the Desktop suite is included, of course. We excluded everything having to do with configuration, for example (which turned out to be rather a lot of tests). Taking advantage of the very nice Silverlight Unit Testing Framework made it pretty easy to reuse our existing VSTS test suite in the Silverlight environment.

What's next?

That's up to you! If you're working on a Silverlight project, please download and let us know what you think! What's important for you? Now's the time, as we're currently prepping for the next version of Enterprise Library and Unity.


Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: .NET | Silverlight | Unity
Actions: E-mail | Permalink | Comments (8) | Comment RSSRSS comment feed

Writing Custom Lifetime Managers

July 15, 2008 11:00 by Chris

 

Note: I'm going to be doing a webcast on extending the Unity container on July 24th. I'm going to be doing the preparation here since I also need to work on the general extension docs anyway. Let's hear it for killing three birds with one stone! In any event, I'd love to get feedback on this doc before I do the webcast. Does it flow well? Make sense? Are you able to write custom lifetime managers after reading this? Thanks!

The Unity Dependency Injection Container has many extension points. One of the easiest to take advantage of is creating custom lifetime managers. A lifetime manager controls how instances are reused within the container. By default, the Unity container creates a new instance every time the Resolve method is called. This can be changed by registering a lifetime manager, like so:

container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager());

With this registration any time an instance of Foo is requested, you'll get back the same one as long as the container is alive.

Since you can pass in any instance of a lifetime manager, it's pretty easy to write your own to customize how object instances get reused. Let's take a look at the LifetimeManager class and how it works within Unity.

The LifetimeManager class

To implement a custom lifetime manager, you need to create a class that derives from Microsoft.Practices.Unity.LifetimeManager. The important methods are:

public abstract class LifetimeManager : ILifetimePolicy
{
    public abstract object GetValue();
    public abstract void SetValue(object newValue);
    public abstract void RemoveValue();
}

It's also important to preserve the semantics of the LifetimeManager. In particular:

  • There is one instance of a LifetimeManager per object that is resolved from the container. Don't try to write a lifetime manager that handles multiple objects at once. The base class and the container enforce this requirement at runtime.
  • Thread safety around your GetValue and SetValue call are your job. We'll see an example of this later.

The container uses the lifetime manager in a fairly straightforward way. If the object in question hasn't been created yet, the sequence looks like this:

Sequence diagram - No object exists 

(Why yes, my handwriting does stink, thanks for noticing :-))

Basically, when a resolve call happens, type mapping happens first (not in the diagram), and then the current lifetime manager is looked up (based on the type and name being resolved). The GetValue method is called, and it returns null. At that point the construction of the object happens, and at the end the SetValue method is called to store the created object for next time.

That next time looks like this:

Sequence - object exists

If GetValue returns something other than null, that becomes the return value of the Resolve call and the rest of the build up process is short-circuited.

Example: Implementing a PerThreadLifetimeManager

Let's look at a sample implementation. One thing that can be useful is a per-thread lifetime: each thread that requests a particular type gets its own instance, but multiple requests from the same thread get the same instance.

The first thing you need to do is decide how you're going to save the instance. In this case, we need some kind of thread local storage (TLS). Luckily, the .NET framework has support for TLS built in. All we need to do is create a static field in our class, and add the [ThreadStatic] attribute. Since this is a static, we'll need to store multiple objects in it (one per PerThreadLifetimeManager). A Dictionary will do the trick. I'm using a Guid as a key because they're an easy way to generate a key. Our class starts off like this:

public class PerThreadLifetimeManager : LifetimeManager
{
    [ThreadStatic]
    private static Dictionary<Guid, object> values;
    private Guid key;

    public PerThreadLifetimeManager()
    {
        key = Guid.NewGuid();
    }

...
}

Now we just need to implement the GetValue and SetValue methods. They're very straightfoward:

public override object GetValue()
{
    InitializeValues();
    if (values.ContainsKey(key))
    {
        return values[key];
    }
    return null;
}

public override void SetValue(object newValue)
{
    InitializeValues();
    values[key] = newValue;
}

private void InitializeValues()
{
    if (values == null)
    {
        values = new Dictionary<Guid, object>();
    }
}

(The InitializeValues method is used to guarantee that each thread gets it's copy of the dictionary properly initialized, see MSDN for more details).

What About RemoveValue?

There's one more method that we have to implement: RemoveValue. This is a little embarrassing, but there's no reason to implement this method. Nothing in the Unity pipeline ever calls RemoveValue. It's there for those doing more advanced extensions, but out of the box it does nothing. The sample code with this article implements it as an empty function that does nothing.

Example: CachedLifetimeManager and Multithreading

Ironically, the PerThreadLifetimeManager class doesn't actually deal with multithreading. The use of TLS meant that we could pretty much ignore concurrency issues. However, as I'm sure you can imagine, proper threading is a major concern in most other lifetime managers. As an example, we'll build one that provides access to a value stored in a cache. This could be the ASP.NET cache, the Enterprise Library caching block, or anything else.

(Sidebar: The ASP.NET cache works just fine in non-ASP.NET applications. Don't let the System.Web namespace prevent you from using this great piece of technology!)

To insulate our code from the details of caching, I've defined a simple interface that does the bare minimum we need - get and retrieve items:

public interface IStorage
{
    object GetObject(string key);
    void StoreObject(string key, object value);
}

It's named IStorage rather than ICache because this is useful for more than just caching. I'm sure you can easily imagine an implementation that maps to the ASP.NET cache; see the code sample for this article for a working one.

When dealing with multithreaded access, the initial approach is usually to do something like this:

public override object GetValue()
{
    lock (lockObj)
    {
        return storage.GetObject(key);
    }
}

Unfortunately, this doesn't work. Look again at the sequence diagram above. If the object isn't in storage, we want to return null. But the lock is released as soon as GetValue returns, and now we're still open to race conditions. What we need to do is take a lock, and if the value is not in storage, hold the lock until SetValue completes. This serializes the object creation process so that we're guaranteed not to new up more objects than we need.

So, we need to hold onto the lock after GetValue returns. This will, I admit, feel a little weird at first. The basic idea is that if there's no object in storage, return without releasing the lock, and then release the lock in the corresponding call to SetValue. Of course, you can't use the lock() statement anymore to do this, so we need to drop down to the lower-level Monitor.Enter and Exit calls. The resulting methods look like this:

public override object GetValue()
{
    Monitor.Enter(lockObj);
    object result = storage.GetObject(key);
    if (result != null)
    {
        Monitor.Exit(lockObj);
    }
    return result;
}

public override void SetValue(object newValue)
{
    storage.StoreObject(key, newValue);
    TryExit();
}

private void TryExit()
{
    try
    {
        Monitor.Exit(lockObj);
    }
    catch (SynchronizationLockException)
    {
        // This is ok, just means we don't hold the lock
    }
}

The TryExit helper method is there because there are circumstances (particularly when you're calling container.RegisterInstance) where you'll call SetValue directly without having gone through GetValue first. The TryExit method avoids throwing an exception if we're not actually holding the lock.

Experienced multithreaded programmers reading this are probably a little worried right now. We exit GetValue holding a lock. What happens if an exception happens and SetValue never gets called? Isn't the lock abandoned at this point? The answer is yes, but there's a safety net.

There's a new interface defined in ObjectBuilder2 called IRequiresRecovery:

public interface IRequiresRecovery
{
    void Recover();
}

The Recover method will be called by ObjectBuilder if an exception happens during the build up process. So, to make sure the lock gets released, we just implement IRequiresRecovery on our lifetime manager:

public class CachedLifetimeManager : LifetimeManager, IRequiresRecovery
{
    ...

    #region IRequiresRecovery Members

    public void Recover()
    {
        TryExit();
    }

    #endregion
}

... and we're all set.

Odds and Ends

We've spent a lot of time talking about how lifetime managers handle creation and retrieval of instances. What about the end of an instance's lifetime? There's a pretty simple hook here: implement IDisposable on your lifetime manager class, and when the container is Disposed, the lifetime manager will be too. This is your opportunity to do whatever cleanup you need. Take a look at the code for the ContainerControlledLifetimeManager for an example.

Our final detail has to do with the container's open generic support. As I said above, there should be one lifetime manager instance per instance being managed. What happens when you do:

container.RegisterType<IRepository<>, CustomRepository<>>(new ContainerControlledLifetimeManager());

You've actually got many different instances at this point, one for each generic type argument: CustomRepository<User>, CustomRepository<Account>, CustomRepository<Flamethrower>, etc. This causes havoc with the semantics of the lifetime manager, and will result in all sorts of weird exceptions down the line.

The solution to this is generally transparent, but is useful to know about. When you register a lifetime manager for an open generic type, the lifetime manager instance to pass in isn't actually used. Instead, the container holds on to the type of the lifetime manager. When creating a closed generic type, it uses the container itself to resolve a new instance of that lifetime manager type.

Normally, you don't care. However, if for some reason you need a lifetime manager that takes constructor parameters, be aware that for open generics the container will be used to create the lifetime manager, and will need to be configured accordingly.

Wrap-up

That's it for lifetime managers. A complete copy of the sample code is available for download below. The unit tests make use of the Moq mock object framework; you'll need to download that separately to compile and run the tests.

TavaresStudios.Unity.zip (11.52 kb)


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: p&p | Unity
Actions: E-mail | Permalink | Comments (9) | Comment RSSRSS comment feed

Do classes need to be DI friendly?

April 25, 2008 10:31 by Chris

I was working on a version of my MSDN magazine Wiki sample (updated code for the April 16 drop coming soon) that used Unity instead of the one-off custom controller factory that is currently in there. I've posted on this before, and my previous conclusions were that it was pretty easy. Of course, I ran into a snag.

The one-off controller factory had this code in it:

[code=C#;ln=on;Original Code]ISpaceRepository GetConfiguredRepository(HttpRequestBase request)
{
    return new FileBasedSpaceRepository(request.MapPath("~/WikiPages"));
}[/code]

Basically, the FileBasedSpaceRepository takes a path to the directory where the files are stored. Of course, in a web app we need to use the server to map from a virtual-directory relative path to a physical file system path. Nothing new or unusual here.

But then I got into replacing this code with Unity, and immediately ran into the question: how do I get the container to call that MapPath method? Unity doesn't know anything about the web. And how does it get the current request?

So, I figured I'd use a child container, shove the request in there, and then use the static factory extension to resolve my string. My controller factory looks like this now:

[code=C#;ln=on;UnityTypeBasedControllerFactory.cs]public class UnityTypeBasedControllerFactory : DefaultControllerFactory
{
    IUnityContainer container;
    public UnityTypeBasedControllerFactory(IUnityContainer container)
    {
        this.container = container;
    }
    protected override IController GetControllerInstance(Type controllerType)
    {
        IUnityContainer requestContainer = container.CreateChildContainer()
            .RegisterInstance<RequestContext>(
                this.RequestContext,
                new ExternallyControlledLifetimeManager());
        return (IController)(requestContainer.Resolve(controllerType));
    }
}[/code]

So basically, what I'm doing here is that for each request, I spin up a child container, stuff the request context into the container, and then resolve the requested controller type. Pretty straightforward.

Next up is to configure the container.

[code=C#;ln=on;GetAPIConfiguredContainer method - first attempt]public static IUnityContainer GetAPIConfiguredContainer()
{
    IUnityContainer container = new UnityContainer()
        .RegisterType<ISpaceRepository, FileBasedSpaceRepository>()
        .Configure<InjectedMembers>()
            .ConfigureInjectionFor<FileBasedSpaceRepository>(
                new InjectionConstructor(
                    new ResolvedParameter<string>("PathToRepositoryFiles")))
            .Container
        .Configure<IStaticFactoryConfiguration>()
            .RegisterFactory<string>("PathToRepositoryFiles",
            c => c.Resolve().HttpContext.Request.MapPath("~/WikiPages"))
        .Container;
    return container;
}[/code]

This is a little grotesque. Instead of just configuring the string to be injected into the constructor, I have to resolve it through the container. I registered the factory delegate (on line 13) to grab the current RequestContext, then use it to resolve the string.

Lots of things wrong here. You can't put this into the config file becuase of that factory method delegate. The actual string is buried in the delegate, so it's not obvious where you're actually getting the path from. And to top it off, due to an unfortunate design decision on my part, the static factory ends up getting the parent container passed into the delegate rather than the child. So the Resolve<RequestContext> call fails.

I found something that works better. I created a new class, MappedPathFileBasedSpaceRepository, which takes the RequestContext and the path to be mapped in the constructor. It inherits from the original FileBasedSpaceRepository, and does the MapPath call before passing the resulting file system path down to the base class. This results in a much, MUCH shorter configuration of the container:

[code=C#;ln=on;GetAPIConfiguredContainer method - better]public static IUnityContainer GetAPIConfiguredContainer()
{
    IUnityContainer container = new UnityContainer()
        .RegisterType<ISpaceRepository, MappedPathFileBasedSpaceRepository>()
        .Configure<InjectedMembers>()
            .ConfigureInjectionFor<MappedPathFileBasedSpaceRepository>(
                new InjectionConstructor(typeof(RequestContext), "~/WikiPages"))
        .Container;
    return container;
}[/code]

I'm pretty happy with where I am now, except for one thing: MappedPathFileBasedSpaceRepository wouldn't exist if I hadn't plugged in the container. Is this just a case of finding a new dependency that I hadn't realized before? Or is it that the presence of the DI container is intruding on my domain model?

I'd love to get some feedback from folks on what you've done to handle issues like this. What's your opinion here?

(I think I like the "child container shove the request context in" approach, but I'd love to get opinions on that too.)


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: .NET | Unity
Actions: E-mail | Permalink | Comments (4) | Comment RSSRSS comment feed