views:

243

answers:

4

Hi

I'm having trouble figuring out how to resolve objects that depend on objects that are non deterministically created at runtime. What is the best approach?

Imagine something like a word processor. For each document you open, you probably want to create a large number of objects that depend on the document object.

As an example, you want to get a hold of an instance of a DocumentEditor:

public class DocumentEditor {
    public DocumentEditor(IDocument document, 
                          ISpellChecker spellChecker, 
                          IWordCounter wordCounter) {
        ...
    }
}

So far, I have considered two approaches but neither seems like a good fit:

Using factories that get injected

The problem with this approach is that you can end up with a factory for each type you need to create. I.e.

public interface ISpellCheckerFactory {
    ISpellChecker Create(IDocument document);
}

public interface IWordCounterFactory {
    IWordCounter Create(IDocument document);
}

public class DocumentEditorFactory {
    public DocumentEditorFactory(ISpellCheckerFactory spellCheckerFactory,
                                 IWordCounterFactory wordCounterFactory) {
        ...
    }

    public DocumentEditor Create(IDocument document) {
        ...
    }
}

Add another 50 classes and you see the problem...

Using nested containers

Using nested containers removes the need to create a zillion factories. It is actually pretty compact (example using Unity):

var child = container.CreateChildContainer();
child.RegisterInstance<IDocument>(theDocument);
child.Resolve<DocumentEditor>();

The drawback of this approach is that the container leaks all over the place.

(As a side note, implementing in unity this is a bit tricky. See for instance: http://stackoverflow.com/questions/530405/unity-how-to-register-types-in-the-main-container-but-resolve-in-a-child-conta)

Hybrid approach

It should be possible to combine the two by implementing a DocumentEditorFactory that creates nested containers and uses the child container to resolve dependencies.

Analysis paralysis at its best...

A: 

Try MEFy approach: you can tread all your SpellCheckers and WordCounters as so-called extensions, which implement say IDocumentEditorExtension interface and are queried at runtime (pseudocode):

IDocumentEditor editor = Registry.Resolve<IDocumentEditor>();
IDocumentEditorExtension[] extensions = Registry.ResolveAll<IDocumentEditorExtension>();

extensions.ForEach((e) => e.AttachTo(editor));
Anton Gogolev
+1  A: 

In autofac there is approach called DelegateFactories. It is a bit similar to your first option however removes the huge amounts of hand coding.

Rashack
A: 

I can suggest you to try AutoFac, because it is very mature in these tracking issues. You register your services to ContainerBuilder and containers you have built keeps track of objects you have requested depending on their scope. Every object marked with ContainerScoped will be disposed when the container is disposed. So you can create a container for each DocumentEditor and dispose container when document is not needed anymore.

http://code.google.com/p/autofac/wiki/NuancesOfTracking

idursun
A: 
Runcible
Interesting read in the related article. However, I fail to see how the described approach would work in this scenario. Would I have a DocumentLifetimeFactory that can create DocumentEditors, ISpellCheckers and IWordCounters? Thats what I'm trying to leverage the container for.
Andreas
That's how I would approach it, yes. The DocumentLifetimeFactory would create DocumntEditors. Do you have a need to create ISpellCheckers and IWordCounters independently of a DocumentEditor? If so, the DocumentLifetimeFactory would be able to create those too.
Runcible
I should mention that I've never used the Unity framework and I'm not sure how it works. If the Unity framework levies some additional requirements on your factories that I'm not familiar with, maybe you can't consolidate your factories as I'm describing.
Runcible