This commit is contained in:
Tagir Ismagilov 2017-10-19 12:55:31 +05:00
Родитель e5a27078a2
Коммит ce03d98592
5 изменённых файлов: 156 добавлений и 2 удалений

Просмотреть файл

@ -414,7 +414,17 @@ namespace Unity.Interception.Interceptors.InstanceInterceptors.InterfaceIntercep
il.Emit(OpCodes.Ceq);
il.Emit(OpCodes.Brtrue_S, noException);
il.Emit(OpCodes.Ldloc, ex);
il.Emit(OpCodes.Throw);
if (ReflectionHelper.ExceptionDispatchInfoCaptureMethod != null
&& ReflectionHelper.ExceptionDispatchInfoThrowMethod != null)
{
il.EmitCall(OpCodes.Call, ReflectionHelper.ExceptionDispatchInfoCaptureMethod, null);
il.EmitCall(OpCodes.Callvirt, ReflectionHelper.ExceptionDispatchInfoThrowMethod, null);
}
else
{
il.Emit(OpCodes.Throw);
}
il.MarkLabel(noException);

Просмотреть файл

@ -416,7 +416,17 @@ namespace Unity.Interception.Interceptors.TypeInterceptors.VirtualMethodIntercep
il.Emit(OpCodes.Ceq);
il.Emit(OpCodes.Brtrue_S, noException);
il.Emit(OpCodes.Ldloc, ex);
il.Emit(OpCodes.Throw);
if (ReflectionHelper.ExceptionDispatchInfoCaptureMethod != null
&& ReflectionHelper.ExceptionDispatchInfoThrowMethod != null)
{
il.EmitCall(OpCodes.Call, ReflectionHelper.ExceptionDispatchInfoCaptureMethod, null);
il.EmitCall(OpCodes.Callvirt, ReflectionHelper.ExceptionDispatchInfoThrowMethod, null);
}
else
{
il.Emit(OpCodes.Throw);
}
il.MarkLabel(noException);

Просмотреть файл

@ -149,5 +149,21 @@ namespace Unity.Interception.Utilities
attributes.AddRange(GetAttributes<TAttribute>(member, inherits));
return attributes.ToArray();
}
public static readonly MethodInfo ExceptionDispatchInfoCaptureMethod;
public static readonly MethodInfo ExceptionDispatchInfoThrowMethod;
static ReflectionHelper()
{
Assembly mscorlib = typeof(int).Assembly;
ExceptionDispatchInfoCaptureMethod = mscorlib
?.GetType("System.Runtime.ExceptionServices.ExceptionDispatchInfo")
?.GetMethod("Capture", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Exception) }, null);
ExceptionDispatchInfoThrowMethod = mscorlib
?.GetType("System.Runtime.ExceptionServices.ExceptionDispatchInfo")
?.GetMethod("Throw", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { }, null);
}
}
}

Просмотреть файл

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.Practices.Unity.InterceptionExtension.Tests.MatchingRules;
using Microsoft.Practices.Unity.InterceptionExtension.Tests.ObjectsUnderTest;
using Microsoft.Practices.Unity.TestSupport;
@ -1669,5 +1670,63 @@ namespace Microsoft.Practices.Unity.InterceptionExtension.Tests.InterfaceInterce
return 0;
}
}
[TestMethod]
public void InterceptorCorrectlyRethrowsException()
{
IUnityContainer container = new UnityContainer()
.AddNewExtension<Interception>()
.RegisterType(typeof(IFoo), typeof(Foo))
.Configure<Interception>()
.SetInterceptorFor(typeof(IFoo), new InterfaceInterceptor())
.AddPolicy("AlwaysMatches")
.AddMatchingRule<AlwaysMatchingRule>()
.AddCallHandler<CallCountHandler>("callCount", new ContainerControlledLifetimeManager())
.Interception
.Container;
IFoo myFoo = container.Resolve<IFoo>();
try
{
myFoo.DoSomething();
Assert.Fail("Should have thrown");
}
catch (Exception ex)
{
CallCountHandler handler = (CallCountHandler)(container.Resolve<ICallHandler>("callCount"));
Assert.AreEqual(1, handler.CallCount);
Assert.IsInstanceOfType(ex, typeof(FooCrashedException));
var stackTrace = ex.StackTrace.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
Assert.IsTrue(stackTrace[0].Contains("DoSomethingLocal"), "stack trace is not full");
}
}
public interface IFoo
{
void DoSomething();
}
public class Foo : IFoo
{
public virtual void DoSomething()
{
DoSomethingLocal();
}
[MethodImpl(MethodImplOptions.NoInlining)]
protected void DoSomethingLocal()
{
throw new FooCrashedException("oops");
}
}
public class FooCrashedException : Exception
{
public FooCrashedException(string message) : base(message)
{
}
}
}
}

Просмотреть файл

@ -12,6 +12,7 @@ using Unity.Interception.Interceptors;
using Unity.Interception.Interceptors.TypeInterceptors.VirtualMethodInterception;
using Unity.Interception.PolicyInjection;
using Unity.Interception.PolicyInjection.Pipeline;
using System.Runtime.CompilerServices;
namespace Microsoft.Practices.Unity.InterceptionExtension.Tests.VirtualMethodInterceptorTests
{
@ -866,6 +867,64 @@ namespace Microsoft.Practices.Unity.InterceptionExtension.Tests.VirtualMethodInt
}
}
}
[TestMethod]
public void InterceptorCorrectlyRethrowsException()
{
IUnityContainer container = new UnityContainer()
.AddNewExtension<Interception>()
.RegisterType(typeof(IFoo), typeof(Foo))
.Configure<Interception>()
.SetInterceptorFor(typeof(Foo), new VirtualMethodInterceptor())
.AddPolicy("AlwaysMatches")
.AddMatchingRule<AlwaysMatchingRule>()
.AddCallHandler<CallCountHandler>("callCount", new ContainerControlledLifetimeManager())
.Interception
.Container;
IFoo myFoo = container.Resolve<IFoo>();
try
{
myFoo.DoSomething();
Assert.Fail("Should have thrown");
}
catch (Exception ex)
{
CallCountHandler handler = (CallCountHandler)(container.Resolve<ICallHandler>("callCount"));
Assert.AreEqual(1, handler.CallCount);
Assert.IsInstanceOfType(ex, typeof(FooCrashedException));
var stackTrace = ex.StackTrace.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
Assert.IsTrue(stackTrace[0].Contains("DoSomethingLocal"), "stack trace is not full");
}
}
public interface IFoo
{
void DoSomething();
}
public class Foo : IFoo
{
public virtual void DoSomething()
{
DoSomethingLocal();
}
[MethodImpl(MethodImplOptions.NoInlining)]
protected void DoSomethingLocal()
{
throw new FooCrashedException("oops");
}
}
public class FooCrashedException : Exception
{
public FooCrashedException(string message) : base(message)
{
}
}
}
public partial class DerivedTypeCreator