The read lock is being released without being held.

Jan 21, 2011 at 12:24 PM

Hi everyone,

I want to Wrap a business object with Policy Injection Transparent Proxy, so I could handle all of the exceptions thrown by this object. To do that, I tried to integrate Unity with Enterprise Library Exception Handling AppBlock. So long, it didn't go so well.

The Unity throws an exception, which has short resources on the internet. I tried to debug through the EL source code, by I got nothing so far.

I would appreciate any kind of help.

First, the error message:

Resolution of the dependency failed, type = "CAFTest3.Library.CreateError", name = "(none)".
Exception occurred while: while resolving.
Exception is: SynchronizationLockException - The read lock is being released without being held.
-----------------------------------------------
At the time of the exception, the container was:

  Resolving CAFTest3.Library.CreateError,(none)

And next, my configuration settings:

            var configBuilder = new ConfigurationSourceBuilder();

            configBuilder.ConfigureLogging()
                .WithOptions
                    .DoNotRevertImpersonation()
                .LogToCategoryNamed("Default Exception Handling")
                    .SendTo
                        .FlatFile("FlatFileListener1")
                            .FormatWith(new FormatterBuilder().TextFormatterNamed("TextFormatter1"))
                        .ToFile("c:\\mylog.txt");


            configBuilder.ConfigureExceptionHandling()
                .GivenPolicyWithName("Default Exception Handling")
                .ForExceptionType<Exception>()
                    .LogToCategory("Default Exception Handling")
                        .UsingExceptionFormatter(typeof(TextExceptionFormatter))
                        .WithSeverity(System.Diagnostics.TraceEventType.Error)
                        .WithPriority(100)
                        .UsingEventId(1200)
                        .UsingTitle("CAF")
                    .WrapWith<Exception>()
                        .UsingMessage("An error has occurred. Please check Inner Exception details.")
                    .ThenThrowNewException();

            var configSource = new DictionaryConfigurationSource();
            configBuilder.UpdateConfigurationWithReplace(configSource);

            ExceptionPolicyFactory f = new ExceptionPolicyFactory(configSource);

            PolicyInjectionSettings config = new PolicyInjectionSettings();

            IUnityContainer container = new UnityContainer();

            container.AddNewExtension<Interception>();
            
            container
                .Configure<Interception>()
                    .AddPolicy("Default Exception Handling")
                    .AddMatchingRule(new CustomAttributeMatchingRule(typeof(AutoHandleExceptionAttribute), false))
                    .AddCallHandler<ExceptionCallHandler>(new ContainerControlledLifetimeManager(), new InjectionConstructor(f.Create("Default Exception Handling")));

            container.RegisterType<CreateError>(
                new Interceptor<TransparentProxyInterceptor>(),
                new InterceptionBehavior<PolicyInjectionBehavior>());


            config.ConfigureContainer(container, configSource);

            configSource.Add(PolicyInjectionSettings.SectionName, config);

            EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);

            IsInitialized = true;

 

And finally, the code that starts the whole operation:

            CreateError err = new CreateError();
            
            CreateError err2 = Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjection.Wrap<CreateError>(err);

            err2.Create();

Despite my efforts, I couldn't find any solution to this problem. The application structure requires that EL should be initialized programmatically, not by configuration xml. But programmatic way is not so comfortable after all.

Any ideas?

Jan 22, 2011 at 12:46 AM

Yeah, this is a bit of a mess. You've got a bunch of issues going on here. The biggest one is you've got three different containers created, and are trying to cross reference objects between them. That's not going to work.

You need to create one container, configure it for Entlib first, and then set it up for use by the core Entlib. You can get rid of the PolicyInjectionSettings completely, you're not actually using it. You can also get rid of the ExceptionPolicyFactory, and instead leverage the container to give you the right object when required.

Rewriting your code above, the following should work:

var configBuilder = new ConfigurationSourceBuilder();

configBuilder.ConfigureLogging()
    .WithOptions
        .DoNotRevertImpersonation()
    .LogToCategoryNamed("Default Exception Handling")
        .SendTo
            .FlatFile("FlatFileListener1")
                .FormatWith(new FormatterBuilder().TextFormatterNamed("TextFormatter1"))
            .ToFile("c:\\mylog.txt");


configBuilder.ConfigureExceptionHandling()
    .GivenPolicyWithName("Default Exception Handling")
    .ForExceptionType<Exception>()
        .LogToCategory("Default Exception Handling")
            .UsingExceptionFormatter(typeof(TextExceptionFormatter))
            .WithSeverity(System.Diagnostics.TraceEventType.Error)
            .WithPriority(100)
            .UsingEventId(1200)
            .UsingTitle("CAF")
        .WrapWith<Exception>()
            .UsingMessage("An error has occurred. Please check Inner Exception details.")
                    .ThenThrowNewException();

var configSource = new DictionaryConfigurationSource();
configBuilder.UpdateConfigurationWithReplace(configSource);

// NEW - Create and initialize container from config source

IUnityContainer container = new UnityContainer()
    .AddExtension(new EnterpriseLibraryCoreExtension(configSource));
    
container
    .Configure<Interception>()
        .AddPolicy("Default Exception Handling")
        .AddMatchingRule(new CustomAttributeMatchingRule(typeof(AutoHandleExceptionAttribute), false))
        .AddCallHandler<ExceptionCallHandler>(new ContainerControlledLifetimeManager(), 
            new InjectionConstructor(new ResolvedParameter<ExceptionPolicyImpl>("Default Exception Handling")));

container.RegisterType<CreateError>(
    new Interceptor<TransparentProxyInterceptor>(),
    new InterceptionBehavior<PolicyInjectionBehavior>());

// NEW - set the configured container to be used by Entlib

EnterpriseLibraryContainer.Current = new UnityServiceLocator(container);

IsInitialized = true;
 

 

 

Jan 24, 2011 at 9:07 AM

Thanks for the solution. Did work :)

Mar 2, 2011 at 2:50 PM

I'm getting the same error message from the following code:

 

            var container = new UnityContainer();
            container.AddNewExtension<Interception>();
            container.AddNewExtension<EnterpriseLibraryCoreExtension>();

            container.Configure<Interception>().AddPolicy("Policy")
                .AddMatchingRule<TypeMatchingRule>( new InjectionConstructor"ExceptionLogging.MyClass" ) )
                .AddCallHandler<ExceptionCallHandler>(
                    new InjectionConstructornew ResolvedParameter<ExceptionPolicyImpl>( "Policy" ) ) );

            container.RegisterType<MyClass>(new InterceptionBehavior<PolicyInjectionBehavior>(),
                                                           new Interceptor<TransparentProxyInterceptor>());

            var myClass = container.Resolve<MyClass>();

            myClass.HelloWorld();

If I register MyClass using and Interface and an InterfaceInterceptor it works.  I'm trying to wrap an existing class without creating an Interface. 
Can anyone help out?

Thanks,

Nick