EntLib's Object Builder Issues: What am I doing wrong?

time to read 23 min | 4457 words

First, let me describe the scenario, I am using Object Builder in a web application to manage the services of the application. Under load, we started to get exceptions from deep within Object Builder. I should also preface this by saying that I have very little knowledge of Object Builder and it is entirely possible that I am commiting some grave error in using it.

Anyway, here is a simple wrapper for Object Builder:

public class BuilderHelper

{

    private Locator _locator = null;

 

    public BuilderHelper():this(new Locator())

    {

    }

    public BuilderHelper(Locator locator)

    {

        this._locator = locator;

        if (!_locator.Contains(typeof(ILifetimeContainer)))

            _locator.Add(typeof(ILifetimeContainer), new LifetimeContainer());

     

    }

 

    public T Build<T>()

    {

        BuilderStrategyChain chain = new BuilderStrategyChain();

        chain.Add(new SingletonStrategy());

        chain.Add(new CreationStrategy());

        PolicyList policies = new PolicyList();

 

        policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy());

 

        BuilderContext builderContext = new BuilderContext(chain, _locator, policies);

        T result;

        result = (T)builderContext.HeadOfChain.BuildUp(builderContext, typeof(T), null, null);

        return result;

 

    }

}

And here is the client code:

[TestClass]

public class StressTestingFixture

{

    private int count = 1000;

 

    [TestMethod]

    public void SimulateHeavyLoad()

    {

        ArrayList list = ArrayList.Synchronized(new ArrayList());

        ManualResetEvent wait = new ManualResetEvent(false);

        Locator locator = new Locator();

        WaitCallback callback = delegate

        {

            wait.WaitOne();//This is required so there will be a lot of threads creating objects at the same time

            try

            {

                BuilderHelper builder = new BuilderHelper(locator);

                Something i1 = builder.Build<Something>();

                if (count % 7 == 0)//need to make sure that GC Collection occurs, so it would clear the WeakRefDictionary

                    GC.Collect(2);

            }

            catch (Exception e)

            {

                string txt = e.ToString();

                Console.WriteLine(txt);

                list.Add(txt);

            }

            finally

            {

                Interlocked.Decrement(ref count);

            }

        };

        for (int i = 0; i < count; i++)

        {

            ThreadPool.QueueUserWorkItem(callback);

        }

        wait.Set();

        while (count > 0 && list.Count == 0)

            Thread.Sleep(15);

        if (list.Count > 0)

        {

            Assert.Fail((string)list[0]);

        }

    }

 

    private class Something

    {

    }

}

The error I am getting:

Assert.Fail failed. System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Microsoft.Practices.ObjectBuilder.WeakRefDictionary`2.Add(TKey key, TValue value) in C:\Documents and Settings\orene\Desktop\Microsoft Enterprise Library January 2006\src\ObjectBuilder\Utility\WeakRefDictionary.cs:line 82
   at Microsoft.Practices.ObjectBuilder.Locator.Add(Object key, Object value) in C:\Documents and Settings\orene\Desktop\Microsoft Enterprise Library January 2006\src\ObjectBuilder\Location\Locator.cs:line 59
   at BuilderHelper..ctor(Locator locator) in C:\Documents and Settings\orene\Desktop\Microsoft Enterprise Library January 2006\UnitTests\ObjectBuilder\BuilderFixture.cs:line 42
   at StressTestingFixture.<>c__DisplayClass1.<SimulateHeavyLoad>b__0(Object ) in C:\Documents and Settings\orene\Desktop\Microsoft Enterprise Library January 2006\UnitTests\ObjectBuilder\StressTestingFixture.cs:line 80

To say that this is worrying is a major understatement...

Any EntLib experts that can shed some light into this?