PolicyInjection.Create throws exception with ExceptionCallHandler

Topics: Exception Handling Application Block, Policy Injection Application Block
Sep 12, 2012 at 4:37 PM

Hi,

I am using Policy Injection Block to inject exception call handler for all types defined in a particular assembly which is already in GAC and using Namespace Matching Rule and Assembly Matching Rule for policy injection.

All classes of the Assembly have ExceptionCallHandler attribute with PolicyName on them. But when i tried to create an object using PolicyInjection.Create. I get the below error. 

I am attaching the configs in the next comment. 

Can you please assist on what's missing? 


Microsoft.Practices.Unity.ResolutionFailedException was unhandled  Message=Resolution of the dependency failed, type = "EnterpriseLibraryExceptionHandling.BankAccount", 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 EnterpriseLibraryExceptionHandling.BankAccount,(none)
  Source=Microsoft.Practices.EnterpriseLibrary.Common  TypeRequested=BankAccount  StackTrace:       at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.TransientPolicyBuildUpExtension.DoBuildUp(Type t, Object existing, String name, InjectionMember[] injectionMembers)       at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.TransientPolicyBuildUpExtension.BuildUp(Type t, Object existing, String name, InjectionMember[] injectionMembers)       at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjector.Wrap(Type typeToReturn, Object instance)       at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjector.Create(Type typeToCreate, Type typeToReturn, Object[] args)       at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjector.Create[TObject](Object[] args)       at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjection.Create[TObject](Object[] args)       at ClientConsole.Module1.Main() in D:\Projects\RND\SharePoint\EnterpriseLibraryExceptionHandling\ClientConsole\Module1.vb:line 22       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)       at System.Threading.ThreadHelper.ThreadStart()  InnerException: System.Threading.SynchronizationLockException       Message=The read lock is being released without being held.       Source=System.Core       StackTrace:            at System.Threading.ReaderWriterLockSlim.ExitReadLock()            at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.ReaderWriterLockExtension.ReaderWriterLockStrategy.ReaderWriterLockCompensator.Recover()            at Microsoft.Practices.ObjectBuilder2.RecoveryStack.ExecuteRecovery()            at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)            at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.TransientPolicyBuildUpExtension.DoBuildUp(Type t, Object existing, String name, InjectionMember[] injectionMembers)       InnerException: 

Sep 12, 2012 at 4:41 PM
Edited Sep 12, 2012 at 4:43 PM
Config Section:
<configSections>
      <section name="policyInjection" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration.PolicyInjectionSettings, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
      <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
      <section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
      <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=2.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </configSections>
Policy Injection Config:
<policyInjection>
    <policies>
      <add name="ExceptionInjectionPolicy">
        <matchingRules>
          <add type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.NamespaceMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            name="Namespace Matching Rule">
            <matches>
              <add match="EnterpriseLibraryExceptionHandling.*" ignoreCase="true" />
            </matches>
          </add>
          <add type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.AssemblyMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            match="EnterpriseLibraryExceptionHandling, EnterpriseLibraryExceptionHandling, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bdf76755e7cb58ba"
            name="Assembly Matching Rule" />
        </matchingRules>
        <handlers>
          <add type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.PolicyInjection.ExceptionCallHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            exceptionPolicyName="ExceptionPolicy" name="ExceptionInjectionPolicyHandler" />
        </handlers>
      </add>
    </policies>
  </policyInjection>
Logging Config
<loggingConfiguration name="Logging" tracingEnabled="true" defaultCategory="Error">
    <listeners>
      <add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        source="Enterprise Library Logging" formatter="Text Formatter"
        log="Application" machineName="." traceOutputOptions="None" />
    </listeners>
    <formatters>
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}"
        name="Text Formatter" />
    </formatters>
    <categorySources>
      <add switchValue="All" name="Error">
        <listeners>
          <add name="Event Log Listener" />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events" />
      <notProcessed switchValue="All" name="Unprocessed Category" />
      <errors switchValue="All" name="Logging Errors &amp; Warnings">
        <listeners>
          <add name="Event Log Listener" />
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>
Exception Handling Config
<exceptionHandling>
    <exceptionPolicies>
      <add name="ExceptionPolicy">
        <exceptionTypes>
          <add name="All Exceptions" type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="None">
            <exceptionHandlers>
              <add name="Logging Exception Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                logCategory="Error" eventId="100" severity="Error" title="Enterprise Library Exception Handling"
                formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                priority="0" />
            </exceptionHandlers>
          </add>
        </exceptionTypes>
      </add>
    </exceptionPolicies>
  </exceptionHandling>
Unity Config
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="CoreExtension" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.EnterpriseLibraryCoreExtension,Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
 
 
    <assembly name="EnterpriseLibraryExceptionHandling"/>
    <namespace name="EnterpriseLibraryExceptionHandling"/>
    <namespace name="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"/>
    <namespace name="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.PolicyInjection" />
    <namespace name="Microsoft.Practices.EnterpriseLibrary.Logging.PolicyInjection" />
    <assembly name="Microsoft.Practices.EnterpriseLibrary.Logging" />
    <container>
      <extension type="CoreExtension"/>
      <extension type="Interception"/>
      <interception>
        <policy name="ExceptionInjectionPolicy" >
        </policy>
      </interception>
    </container>
  </unity>
Sep 13, 2012 at 8:02 PM

Can you post a code sample as well?  e.g. the BankAccount class and how you are creating/using the object.

Thanks.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Sep 13, 2012 at 8:20 PM

Here is a working example using Unity and an ExceptionCallHandler:

    public interface IService
    {
        void Process();
    }

    public class Service : IService
    {
        [ExceptionCallHandler("ExceptionPolicyName")]
        public void Process()
        {
            throw new NotImplementedException();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IUnityContainer container =  new UnityContainer().LoadConfiguration();

            IService service = container.Resolve<IService>();

            try
            {
                service.Process();
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception was replaced: " + (e is ApplicationException));
                Console.WriteLine(e.Message);
            }
        }
    }

And the configuration:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <exceptionHandling>
    <exceptionPolicies>
      <add name="ExceptionPolicyName">
        <exceptionTypes>
          <add name="NotImplementedException" type="System.NotImplementedException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="ThrowNewException">
            <exceptionHandlers>
              <add name="Replace Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ReplaceHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                exceptionMessage="Oops!  An invalid operation occurred!" replaceExceptionType="System.ApplicationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            </exceptionHandlers>
          </add>
        </exceptionTypes>
      </add>
    </exceptionPolicies>
  </exceptionHandling>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="IService" type="UnityExceptionHandling.IService, UnityExceptionHandling" />
    <alias alias="Service" type="UnityExceptionHandling.Service, UnityExceptionHandling" />
    <alias alias="EnterpriseLibraryCoreExtension" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.EnterpriseLibraryCoreExtension, Microsoft.Practices.EnterpriseLibrary.Common"/>

    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
    
    <container>
      <extension type="Interception" />
      <extension type="EnterpriseLibraryCoreExtension" />
      <register type="IService" mapTo="Service">
        <interceptor type="InterfaceInterceptor"/>
        <policyInjection />
      </register>
    </container>
  </unity>
</configuration>

Hopefully that helps.
--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Sep 13, 2012 at 8:40 PM
Edited Sep 13, 2012 at 8:42 PM

I know this example but can't go on this path because the requirement is to enable the exception handling on the existing classes, methods in the assembly/source without too much source code modifications. So, defining interface and implementing it on the classes is not a good option.

As far as code for creating the object is concerned, here is the sample.

BankAccount Object Creation

Dim account As BankAccount = PI.PolicyInjection.Create(Of EnterpriseLibraryExceptionHandling.BankAccount)()

BankAccount class code with ExceptionCallHandler attribute.

<ExceptionCallHandler(CONSTANTS.EXCEPTION_POLICY_NAME)>
Public Class BankAccount
 
    Public Sub New()
 
    End Sub
 
 
    Public Shared Sub SharedSubWithoutParameters()
        Throw New ApplicationException(MethodBase.GetCurrentMethod().ToString())
    End Sub
 
    Public Shared Sub SharedSubWithParameters(ByVal param As String)
        Throw New ApplicationException(MethodBase.GetCurrentMethod().ToString())
    End Sub
 
    Public Shared Function SharedFunctionWithoutParameter() As Boolean
        Throw New ApplicationException(MethodBase.GetCurrentMethod().ToString())
    End Function
 
    Public Shared Function SharedFunctionWithParameter(ByVal param As StringAs Boolean
        Throw New ApplicationException(MethodBase.GetCurrentMethod().ToString())
    End Function
 
    Public Sub InstanceSubWithoutParameters()
        Throw New ApplicationException(MethodBase.GetCurrentMethod().ToString())
    End Sub
    Public Sub InstanceSubWithParameters(ByVal param As String)
        Throw New ApplicationException(MethodBase.GetCurrentMethod().ToString())
    End Sub
 
    Public Function InstanceFunctionWithoutParameter() As Boolean
        Throw New ApplicationException(MethodBase.GetCurrentMethod().ToString())
    End Function
 
    Public Function InstanceFunctionWithParameter(ByVal param As StringAs Boolean
        Throw New ApplicationException(MethodBase.GetCurrentMethod().ToString())
    End Function
 
 
 
End Class



Please let me know if you need the complete solution and how can i upload/share?
Sep 14, 2012 at 5:01 AM

In order to intercept method calls  the class will have to be able to be intercepted.  This means it needs to be an interface, inherit from MarshalByRefObject, or expose public or protected virtual methods.  See Unity Interception Techniques and Using Interception and Policy Injection.  So the BankAccount is not currently interceptable.

It looks to me that if you use PolicyInjection.Create() the class must inherit MarshalByRefObject. 

If you look at the Hands-On Labs for Microsoft Enterprise Library 5.0 Policy Injection Lab 10 there is a good example using straight policy injection in config with a CallHandler.

So you must first modify your class methods to support at least one of the 3 interceptors.  Once you do that then you can wire up the interception.  Depending on the implementation you may not have a lot of changes;  refactoring tools (Visual Studio or others) can extract interfaces from a class so you may only have to extract the interface and mark the class as implementing the interface.

Also, since you are using the static PolicyInjection facade, the Unity configuration is not used.

Since you seem averse to interfaces and I think that forcing all classes to extend MarshalByRefObject is usually not practical then you could just make all methods virtual:

    [ExceptionCallHandler("ExceptionPolicyName")]
    public class BankAccount
    {
        public virtual void DoSomething()
        {
            throw new NotImplementedException();
        }
    }


    IUnityContainer container =  new UnityContainer().LoadConfiguration();

    BankAccount account = container.Resolve<BankAccount>();
            
    try
    {
        account.DoSomething();
    }
    catch (Exception e)
    {
        Console.WriteLine("Exception was replaced: " + (e is ApplicationException));
        Console.WriteLine(e.Message);
    }

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <exceptionHandling>
    <exceptionPolicies>
      <add name="ExceptionPolicyName">
        <exceptionTypes>
          <add name="NotImplementedException" type="System.NotImplementedException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="ThrowNewException">
            <exceptionHandlers>
              <add name="Replace Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ReplaceHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                exceptionMessage="Oops!  An invalid operation occurred!" replaceExceptionType="System.ApplicationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            </exceptionHandlers>
          </add>
        </exceptionTypes>
      </add>
    </exceptionPolicies>
  </exceptionHandling>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="BankAccount" type="UnityExceptionHandling.BankAccount, UnityExceptionHandling" />
    <alias alias="EnterpriseLibraryCoreExtension" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.EnterpriseLibraryCoreExtension, Microsoft.Practices.EnterpriseLibrary.Common"/>

    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
    
    <container>
      <extension type="Interception" />
      <extension type="EnterpriseLibraryCoreExtension" />
      <register type="IService" mapTo="Service">
        <interceptor type="VirtualMethodInterceptor"/>
        <policyInjection />
      </register>
      <register type="BankAccount">
        <interceptor type="VirtualMethodInterceptor"/>
        <policyInjection />
      </register>
    </container>
  </unity>
</configuration>

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com