UnityContainer.IsRegistered() : Value cannot be null.

Feb 11, 2014 at 2:41 AM
I use unity 2.0.414.0 (.Net 3.5)。
Sometimes to get an exception message: “Value cannot be null. Parameter name: key” in production WCF servers. Resetting IIS or App pool on that WCF server solve this problem. I am not able to reproduce this issue on development environments.

It appears to be using IsRegistered() and thus suffers from the performance issues described above.

System.ArgumentNullException: Value cannot be null.
Parameter: key
at System.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
at System.Collections.Generic.Dictionary2.FindEntry(TKey key)
at System.Collections.Generic.Dictionary
2.ContainsKey(TKey key)
at Microsoft.Practices.Unity.UnityContainer.FillTypeRegistrationDictionary(IDictionary`2 typeRegistrations)
at Microsoft.Practices.Unity.UnityContainer.get_Registrations()
at Microsoft.Practices.Unity.UnityContainerExtensions.IsRegistered(IUnityContainer container, Type typeToCheck, String nameToCheck)
at Better.Wcf.UnityInstanceProvider.GetInstance(InstanceContext instanceContext, Message message)

the code:
        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            Type serviceType = instanceContext.Host.Description.ServiceType;
            if (!Container.IsRegistered(this._serviceContractType))
            {
                Container.RegisterType(this._serviceContractType, serviceType);
                Container.Configure<Interception>().SetInterceptorFor(this._serviceContractType, new InterfaceInterceptor());
            }

            return container.Resolve(this._serviceContractType);
        }
Any help on this is greatly appreciated.
Feb 12, 2014 at 4:48 AM
The issue that you are seeing is that you are running in a multi-threaded environment (IIS) but the posted code is not thread-safe. In general, Resolve and BuildUp are thread-safe but everything else is not guaranteed to be thread-safe.

So to avoid this issue you should synchronize access to the non-Resolve methods.

I'm curious why you need to check for registrations and then register types as requests come in. Is it for performance reasons? The preferred pattern is to register all types at application startup and then just resolve on all incoming requests (this is ideal but sometimes it doesn't fit with the requirements). IsRegistered is not particularly fast and once locking is introduced it would be less so. Perhaps a lighter-weight concurrent dictionary to check if you've already registered a type?

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to