16

Closed

VirtualMethodInterceptor does not work with EntLib DataAccessBlock.

description

<p>We want to be able to intercept method calls to the EntLib DAB&#39;s Database class. Specifically we want to intercept ExecuteReader, ExecuteNonQuery, etc, to create a CallHandler which logs the SQL which is being executed. Unfortunately we get this error when we try to use interception.</p> <p>&nbsp;</p> <p>Microsoft.Practices.Unity.ResolutionFailedException was unhandled</p> <p> Message=&quot;Resolution of the dependency failed, type = \&quot;Microsoft.Practices.EnterpriseLibrary.Data.Database\&quot;, name = \&quot;Default\&quot;. Exception message is: The current build operation (build key Build Key[Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase, Default]) failed: The current build operation (build key Build Key[Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase, Default]) failed: Value cannot be null.\r\nParameter name: str (Strategy type DynamicMethodConstructorStrategy, index 0) (Strategy type BuildPlanStrategy, index 5)&quot;</p> <p> Source=&quot;Microsoft.Practices.Unity&quot;</p> <p> NameRequested=&quot;Default&quot;</p> <p> TypeRequested=&quot;Database&quot;</p> <p> StackTrace:</p> <p> at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name)</p> <p> at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name)</p> <p> at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name)</p> <p> at Microsoft.Practices.Unity.UnityContainerBase.Resolve[T](String name)</p> <p> at UnityScratch.Program.Main(String[] args) in C:\Users\mattdot\Documents\Visual Studio 2008\Projects\UnityScratch\UnityScratch\Program.cs:line 31</p> <p> at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)</p> <p> at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()</p> <p> at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)</p> <p> at System.Threading.ThreadHelper.ThreadStart()</p> <p> InnerException: Microsoft.Practices.ObjectBuilder2.BuildFailedException</p> <p> Message=&quot;The current build operation (build key Build Key[Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase, Default]) failed: The current build operation (build key Build Key[Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase, Default]) failed: Value cannot be null.\r\nParameter name: str (Strategy type DynamicMethodConstructorStrategy, index 0) (Strategy type BuildPlanStrategy, index 5)&quot;</p> <p> Source=&quot;Microsoft.Practices.ObjectBuilder2&quot;</p> <p> BuildKey=&quot;Build Key[Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase, Default]&quot;</p> <p> ExecutingStrategyIndex=5</p> <p> ExecutingStrategyTypeName=&quot;BuildPlanStrategy&quot;</p> <p> StackTrace:</p> <p> at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)</p> <p> at Microsoft.Practices.ObjectBuilder2.Builder.BuildUp(IReadWriteLocator locator, ILifetimeContainer lifetime, IPolicyList policies, IStrategyChain strategies, Object buildKey, Object existing)</p> <p> at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name)</p> <p> InnerException: Microsoft.Practices.ObjectBuilder2.BuildFailedException</p> <p> Message=&quot;The current build operation (build key Build Key[Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase, Default]) failed: Value cannot be null.\r\nParameter name: str (Strategy type DynamicMethodConstructorStrategy, index 0)&quot;</p> <p> Source=&quot;Microsoft.Practices.ObjectBuilder2&quot;</p> <p> BuildKey=&quot;Build Key[Microsoft.Practices.EnterpriseLibrary.Data.GenericDatabase, Default]&quot;</p> <p> ExecutingStrategyIndex=0</p> <p> ExecutingStrategyTypeName=&quot;DynamicMethodConstructorStrategy&quot;</p> <p> StackTrace:</p> <p> at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)</p> <p> at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlanCreatorPolicy.CreatePlan(IBuilderContext context, Object buildKey)</p> <p> at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)</p> <p> at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)</p> <p> InnerException: System.ArgumentNullException</p> <p> Message=&quot;Value cannot be null.\r\nParameter name: str&quot;</p> <p> Source=&quot;mscorlib&quot;</p> <p> ParamName=&quot;str&quot;</p> <p> StackTrace:</p> <p> at System.Reflection.Emit.DynamicILGenerator.Emit(OpCode opcode, String str)</p> <p> at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.PreBuildUp(IBuilderContext context)</p> <p> at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)</p> <p> InnerException: </p> <p>&nbsp;</p> <p>Here is some sample code:</p> <p>&nbsp;</p> <p>using System;</p> <p>using System.Collections.Generic;</p> <p>using System.Linq;</p> <p>using System.Text;</p> <p>using Microsoft.Practices.Unity;</p> <p>using Microsoft.Practices.EnterpriseLibrary.Data;</p> <p>using System.Data;</p> <p>using System.Data.Common;</p> <p>using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity;</p> <p>using Microsoft.Practices.EnterpriseLibrary.Data.Configuration.Unity;</p> <p>using System.Diagnostics;</p> <p>using Microsoft.Practices.Unity.InterceptionExtension;</p> <p>&nbsp;</p> <p>namespace UnityScratch</p> <p>{</p> <p> class Program</p> <p> {</p> <p> static void Main(string[] args)</p> <p> {</p> <p> IUnityContainer container = new UnityContainer();</p> <p> container.AddNewExtension&lt;EnterpriseLibraryCoreExtension&gt;();</p> <p> container.AddNewExtension&lt;DataAccessBlockExtension&gt;();</p> <p>&nbsp;</p> <p> container.AddNewExtension&lt;Interception&gt;();</p> <p> container.Configure&lt;Interception&gt;()</p> <p> .SetDefaultInterceptorFor&lt;GenericDatabase&gt;(new VirtualMethodInterceptor());</p> <p> .AddPolicy(&quot;SQLTRACE&quot;)</p> <p> .AddMatchingRule&lt;ExecuteMatchingRule&gt;()</p> <p> .AddCallHandler&lt;SqlLoggerCallHandler&gt;();</p> <p>&nbsp;</p> <p> Database db = container.Resolve&lt;Database&gt;(&quot;Default&quot;);</p> <p> DbCommand cmd = db.GetStoredProcCommand(&quot;getroles&quot;);</p> <p>&nbsp;</p> <p> db.AddInParameter(cmd, &quot;p_Id&quot;, DbType.Int64, 1234);</p> <p>&nbsp;</p> <p> using (IDataReader reader = db.ExecuteReader(cmd))</p> <p> {</p> <p> while (reader.Read())</p> <p> {</p> <p> Debug.Print(reader.GetString(1));</p> <p> }</p> <p> }</p> <p> }</p> <p> }</p> <p>&nbsp;</p> <p> public class ExecuteMatchingRule : IMatchingRule</p> <p> {</p> <p> #region IMatchingRule Members</p> <p>&nbsp;</p> <p> public bool Matches(System.Reflection.MethodBase member)</p> <p> {</p> <p> return member.Name.StartsWith(&quot;Execute&quot;);</p> <p> }</p> <p>&nbsp;</p> <p> #endregion</p> <p> }</p> <p>&nbsp;</p> <p>&nbsp;</p> <p> public class SqlLoggerCallHandler : ICallHandler</p> <p> {</p> <p>&nbsp;</p> <p> #region ICallHandler Members</p> <p>&nbsp;</p> <p> public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)</p> <p> {</p> <p> IMethodReturn msg = getNext()(input, getNext);</p> <p>&nbsp;</p> <p> return msg;</p> <p> }</p> <p>&nbsp;</p> <p> public int Order</p> <p> {</p> <p> get;</p> <p> set;</p> <p> }</p> <p>&nbsp;</p> <p> #endregion</p> <p> }</p> <p>}</p>

file attachments

Closed Aug 7, 2009 at 11:37 PM by
Duplicate

comments

Chernichkin wrote Feb 4, 2009 at 6:37 PM

VirtualMethodInterceptor fails when type has constructor with parameters. Probably here same issue. I wonder no one haven't noticed this yet.

abombss wrote Jun 1, 2009 at 11:35 PM

WTF -- How can software really be released like this... This is really really bad and I hope it gets fixed tomorrow or I am hosed.

abombss wrote Jun 1, 2009 at 11:37 PM

[TestFixture]
public class BasicResolutionTest
{
    [Test]
    [Category("Integration")]
    public void Can_Resolve_Public_Dependencies_With_A_VirtualInterceptor()
    {
        // Arrange
        var container = new UnityContainer();
        container.AddNewExtension();
        container.RegisterType();
        container.RegisterType();
        container.Configure()
            .SetInterceptorFor(new VirtualMethodInterceptor());

        // Act
        var rootService = container.Resolve();

        // Assert
        // It never gets here
        Assert.IsNotNull(rootService);
    }


}

public class RootService
{
    public ChildService ChildService { get; set; }

    public RootService(ChildService child)
    {
        ChildService = child;
    }

    public virtual void Foo()
    {

    }
}

public class ChildService
{
}

abombss wrote Jun 1, 2009 at 11:37 PM

------ Test started: Assembly: Ttx.Tests.CarCharacteristics.NUnit.dll ------

TestCase 'Ttx.Tests.CarCharacteristics.Framework.EnterpriseLibrary.Unity.Interception.BasicResolutionTest.Can_Resolve_Public_Dependencies_With_A_VirtualInterceptor'
failed: Microsoft.Practices.Unity.ResolutionFailedException : Resolution of the dependency failed, type = "Ttx.Tests.CarCharacteristics.Framework.EnterpriseLibrary.Unity.Interception.RootService", name = "". Exception message is: The current build operation (build key Build Key[Ttx.Tests.CarCharacteristics.Framework.EnterpriseLibrary.Unity.Interception.RootService, null]) failed: The current build operation (build key Build Key[Ttx.Tests.CarCharacteristics.Framework.EnterpriseLibrary.Unity.Interception.RootService, null]) failed: Value cannot be null.
Parameter name: str (Strategy type DynamicMethodConstructorStrategy, index 0) (Strategy type BuildPlanStrategy, index 5)
----> Microsoft.Practices.ObjectBuilder2.BuildFailedException : The current build operation (build key Build Key[Ttx.Tests.CarCharacteristics.Framework.EnterpriseLibrary.Unity.Interception.RootService, null]) failed: The current build operation (build key Build Key[Ttx.Tests.CarCharacteristics.Framework.EnterpriseLibrary.Unity.Interception.RootService, null]) failed: Value cannot be null.
Parameter name: str (Strategy type DynamicMethodConstructorStrategy, index 0) (Strategy type BuildPlanStrategy, index 5)
----> Microsoft.Practices.ObjectBuilder2.BuildFailedException : The current build operation (build key Build Key[Ttx.Tests.CarCharacteristics.Framework.EnterpriseLibrary.Unity.Interception.RootService, null]) failed: Value cannot be null.
Parameter name: str (Strategy type DynamicMethodConstructorStrategy, index 0)
----> System.ArgumentNullException : Value cannot be null.
Parameter name: str
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name)
at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name)
at Microsoft.Practices.Unity.UnityContainerBase.Resolve[T]()
C:\export\code\ttx.carchar\trunk\Engineering\Tests\Ttx.Tests.CarCharacteristics.NUnit\Framework\EnterpriseLibrary\Unity\Interception\BasicResolutionTest.cs(26,0): at Ttx.Tests.CarCharacteristics.Framework.EnterpriseLibrary.Unity.Interception.BasicResolutionTest.Can_Resolve_Public_Dependencies_With_A_VirtualInterceptor()
--BuildFailedException
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.Builder.BuildUp(IReadWriteLocator locator, ILifetimeContainer lifetime, IPolicyList policies, IStrategyChain strategies, Object buildKey, Object existing)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name)
--BuildFailedException
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlanCreatorPolicy.CreatePlan(IBuilderContext context, Object buildKey)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
--ArgumentNullException
at System.Reflection.Emit.DynamicILGenerator.Emit(OpCode opcode, String str)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)

abombss wrote Jun 2, 2009 at 12:06 AM

Fixed the problem, Unity it would be nice if you dog fooded a little bit or even had some test coverage, this fix is so simply.

Line 80 of DynamicMethodConstructorStrategy should be changed from
buildContext.IL.Emit(OpCodes.Ldstr, parameters[i].Name);
to
buildContext.IL.Emit(OpCodes.Ldstr, parameters[i].Name ?? string.Empty);

I hope this gets fixed soon and released.