我正在努力学习Unity拦截器,我正在努力学习它.
说我有这样的界面:
public interface IMyInterface
{
void SomeMethod();
}
Run Code Online (Sandbox Code Playgroud)
我有一个未知数量的类实现该接口,如下所示:
public class SpecificClass1 : IMyInterface
{
public void SomeMethod()
{
Console.WriteLine("Method Called");
}
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种方式来说,"对于IMyInterface的所有实例(我不想枚举它们),当调用SomeMethod时运行我的拦截器.
这是克拉斯的非列举给我带来麻烦.(如果你能列举所有的课程,有很多例子.)
我读过类型拦截,但我似乎无法找出它是否能满足我的要求.
那里的任何Unity专家都知道如何做我想要的东西?
我有一个实现两个接口的类,我想对类的方法应用拦截.
我遵循Unity中的建议将两个接口作为一个单独的接口,但我对结果感到惊讶.简而言之,似乎我的CallHandler被调用了两次.我有一个最简单的例子是:
public interface I1
{
void Method1();
}
public interface I2
{
void Method2();
}
public class C : I1, I2
{
[Log]
public void Method1() {}
public void Method2() {}
}
public class LogAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new LogCallHandler();
}
}
public class LogCallHandler : ICallHandler
{
public IMethodReturn Invoke(
IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine("Entering " + input.MethodBase.Name);
var methodReturn = getNext().Invoke(input, getNext);
Console.WriteLine("Leaving " + …Run Code Online (Sandbox Code Playgroud) 我创建了自己的行为,如下所示:
public class BoundaryExceptionHandlingBehavior : IInterceptionBehavior
{
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
try
{
return getNext()(input, getNext);
}
catch (Exception ex)
{
return null; //this would be something else...
}
}
public bool WillExecute
{
get { return true; }
}
}
Run Code Online (Sandbox Code Playgroud)
我已正确设置它,以便我的行为按预期命中.但是,如果在任何getNext()中发生任何异常,它都不会触及我的catch块.谁能澄清为什么?我并不是真的想要解决问题,因为有许多方法可以处理异常,更多的是我不明白发生了什么,我想.
我们正在研究使用Unity来处理带有拦截的日志服务方法.但是,一个问题是呼叫站点没有完整的堆栈跟踪; 它只在拦截器调用中可用.
这是一个示例设置:
public interface IExceptionService
{
void ThrowEx();
}
public class ExceptionService : IExceptionService
{
public void ThrowEx()
{
throw new NotImplementedException();
}
}
public class DummyInterceptor : IInterceptionBehavior
{
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
IMethodReturn ret = getNext()(input, getNext);
if (ret.Exception != null)
Console.WriteLine("Interceptor: " + ret.Exception.StackTrace + "\r\n");
return ret;
}
public bool WillExecute
{
get { return true; }
}
}
class Program
{
static void Main(string[] …Run Code Online (Sandbox Code Playgroud) 我正在关注Unity Interception链接,在我的项目中实现Unity.
通过链接我创建了一个类,如下所示:
[AttributeUsage(AttributeTargets.Method)]
public class MyInterceptionAttribute : Attribute
{
}
public class MyLoggingCallHandler : ICallHandler
{
IMethodReturn ICallHandler.Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn result = getNext()(input, getNext);
return result;
}
int ICallHandler.Order { get; set; }
}
public class AssemblyQualifiedTypeNameConverter : ConfigurationConverterBase
{
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (value != null)
{
Type typeValue = value as Type;
if (typeValue == null)
{
throw new ArgumentException("Cannot convert type", typeof(Type).Name); …Run Code Online (Sandbox Code Playgroud) 我希望使用WithMappings.FromMatchingInterface约定将实现特定接口的所有类注册到Unity中.另外,我希望使用接口拦截行为拦截所有已注册的对象.问题是Unity还注册了具体类之间的映射,当这些类被解析时,会抛出一个异常消息:
"[类型]不可拦截"
我意识到使用具体类类型解析对象不是最佳实践,但我想知道为什么Unity会自动为接口添加映射 - >具体类以及具体类 - >按惯例注册时的具体类?这意味着如果添加接口拦截器并使用具体类型解析它将永远不会工作.
我希望得到的结果是Unity在按惯例注册并给它一个接口拦截器时没有添加具体类型 - >具体类型映射,这样我们就可以使用它的具体类型来解析类,如果我们愿意,我们只是没有拦截.
我不想使用VirtualMethodInterceptor因为我不想对类进行更改以便拦截工作,这包括继承MarshalByRef.我还想避免单独注册所有对象.
因此,我的问题是,如何按惯例注册时只注册接口映射?
更新:单独注册类会产生相同的问题,因此假设一旦对象使用interfaceinterceptor注册,则无法通过使用具体类型来解析它.
新注册码:
container.RegisterType<ISomeService, SomeService>(new InjectionMember[]
{
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<TraceInterceptor>()
});
container.RegisterType<ISomeRepository, SomeRepository>(new InjectionMember[]
{
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<TraceInterceptor>()
});
Run Code Online (Sandbox Code Playgroud)
更新2为所有接口添加默认拦截器似乎工作,虽然这个解决方案相当hacky.该解决方案在按惯例进行标准注册之前需要一些代码,并且InterfaceInterceptor在基于约定的注册中删除.
预注册代码
foreach (var type in types)
{
container
.Configure<Interception>()
.SetDefaultInterceptorFor(type.GetInterface("I" + type.Name), new InterfaceInterceptor());
}
Run Code Online (Sandbox Code Playgroud)
一些解释困境的代码:
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using System;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{ …Run Code Online (Sandbox Code Playgroud) 看起来Unity似乎提供了两种不同的路线来实现AoP功能.
问题是为什么?有什么区别?每种方法的优缺点是什么?
例如,使用ICallHandler:
unity.Configure<Interception>()
.AddMatchingRule(
new TypeMatchingRule(typeof (ComplexEntity))
).AddMatchingRule(
new TypeMatchingRule(typeof (ComplexEntity.InnerEntity))
).AddMatchingRule(
new MemberNameMatchingRule("*")
).AddCallHandler(
new CallHandler()
);
Run Code Online (Sandbox Code Playgroud)
但是使用IInterceptionBehavior代替ICallHandler也可以实现类似的功能
unity.RegisterType<ComplexEntity,ComplexEntity>
(new VirtualMethodInterceptor(), new InterceptionBehavior)
Run Code Online (Sandbox Code Playgroud)
还有一个混合某处可以让你设置拦截,但使用一个调用处理程序,例如.
unity.Configure<Interception>()
.SetInterceptorFor<ComplexEntity>(new VirtualMethodInterceptor())
.AddPolicy("TestPolicy")
.AddMatchingRule(
new TypeMatchingRule(typeof (ComplexEntity))
).AddMatchingRule(
new TypeMatchingRule(typeof (ComplexEntity.InnerEntity))
).AddMatchingRule(
new MemberNameMatchingRule("*")
).AddCallHandler(
new CallHandler()
);
Run Code Online (Sandbox Code Playgroud)
那么哪一个使用?为什么在单一框架中存在看似冗余的解决方案?
c# aop dependency-injection unity-container unity-interception
我想获得这里答案中描述的行为,但通过代码使用配置。代码示例显示创建的自定义属性没有任何与统一相关的内容,并通过配置添加行为。
自定义属性位于同一解决方案中引用的单独程序集中。
问题是它在配置过程中抛出异常:
InvalidOperationException:Microsoft.Practices.Unity.InterceptionExtension.CustomAttributeMatchingRule 类型没有采用参数(LogAttribute、Boolean)的构造函数。
container
.AddNewExtension<Interception>()
.Configure<Interception>()
.AddPolicy("MyLoggingPolicy")
.AddMatchingRule<CustomAttributeMatchingRule>(
new InjectionConstructor(typeof(Abstractions.Attributes.LogAttribute), true))
.AddCallHandler<LoggingHandler>(new ContainerControlledLifetimeManager())
.Interception
.Container
.RegisterType<IFirstInterface>(new InjectionFactory((context) => FirstClassFactoryMethod()))
.RegisterType<ISecondInterface>(new InjectionFactory((context) => SecondClassFactoryMethod()));
[AttributeUsage(AttributeTargets.Method)]
public class LogAttribute : Attribute { }
public class LoggingHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")} Started: {input.MethodBase.Name}");
var result = getNext()(input, getNext);
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")} Completed: {input.MethodBase.Name}");
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
更新抛出的行:
.AddMatchingRule(
new CustomAttributeMatchingRule(typeof(Abstractions.Attributes.LogAttribute), true))
Run Code Online (Sandbox Code Playgroud)
防止抛出异常,但 LoggingHandler 不会收到来自具有 …
我继承了这个项目,我通常不统一作为我的依赖解析器,所以请原谅我,如果这是一个愚蠢的问题。
当我尝试解决接口时,我收到以下消息。
内部异常1:
InvalidOperationException:没有可用于类型 [ProjectName].ITest 的公共构造函数
内部异常2:
InvalidRegistrationException:引发了“Unity.Exceptions.InvalidRegistrationException”类型的异常。
现在,在有人跳到我身上并说我没有构造函数之前,该类看起来像这样......它有一个没有参数的构造函数。
namespace ProjectName
{
public class Test : ITest
{
public Test()
{
}
public int Foo() => 99;
}
public interface ITest
{
int Foo();
}
}
Run Code Online (Sandbox Code Playgroud)
所以有一个没有参数的构造函数 这是试图解析该类的类。
[Route("api/Test")]
public class TestController : ApiController
{
[Dependency]
public ITest Test { get; set; }
public TestController()
{
}
[HttpPost]
public IHttpActionResult Post()
{
var i = Test.Foo();
return Ok();
}
}
Run Code Online (Sandbox Code Playgroud) asp.net unity中的接口拦截和构造函数注入有什么区别?我缺乏对Unity的理解我正在研究一个旧项目和unity.config,有些像这样,
<register type="ICRIC2012TrialUserService" mapTo="CRIC2012TrialUserService">
<lifetime type="perthread"/>
<interceptor type="InterfaceInterceptor"/>
<policyInjection/>
</register>
Run Code Online (Sandbox Code Playgroud)
但有些人没有
<interceptor type="InterfaceInterceptor"/>
Run Code Online (Sandbox Code Playgroud)
但是在项目中,这些类和接口以相同的方式工作,就像这样
private readonly IIncomingEstimateService _incomingEstimateService;
public ContractService(IIncomingEstimateService incomingEstimateService)
{
_incomingEstimateService = incomingEstimateService;
}
Run Code Online (Sandbox Code Playgroud) 我在这里描述的问题没有答案,仅使用Unity.
我正在尝试注册ISecureDataFormat<>最新的VS2013(更新2)SPA/Web Api模板.
我试过了
container.RegisterType(typeof(ISecureDataFormat<>), typeof(SecureDataFormat<>));
container.RegisterType<ISecureDataFormat<AuthenticationTicket>, SecureDataFormat<AuthenticationTicket>>();
container.RegisterType<ISecureDataFormat<AuthenticationTicket>, TicketDataFormat>();
Run Code Online (Sandbox Code Playgroud)
它"有效"但不是真的,因为它抱怨了该树中的下一个依赖性,IDataSerializer ......然后是下一个IDataProtector,我发现没有实现.
对于我的单元测试我目前正在使用Moq模拟我的拦截器和拦截类,然后在Unity中注册截获的实例并为接口设置默认拦截器.然后我解析实例并调用截获的方法并验证是否正在调用拦截方法.
_mockInterceptor = new Mock<ExternalInterceptor>().As<IInterceptRelay>();
_mockInterception = new Mock<TestInterception> { CallBase = true }.As<IInterceptRelay>();
Container.RegisterInstance(_mockInterception.Object as ITestInterception);
UnityContainer.Configure<Interception>().SetDefaultInterceptorFor<ITestInterception>(new InterfaceInterceptor());
var test = Container.Resolve<ITestInterception>();
var returnValue = test.TestTheExternalInterception(TestMessage);
_mockInterceptor.Verify(i => i.ExecuteAfter(It.IsAny<object>(), It.IsAny<IEnumerable>(), It.IsAny<LoggingInterceptionAttribute>(), It.IsAny<IMethodResult>()), Times.Once());
Run Code Online (Sandbox Code Playgroud)
这很好用,但是我宁愿在注册期间设置拦截,就像我在注册服务/单例时保持一致性一样.
// Typical registration
UnityContainer.RegisterType<TFrom, TTo>(new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<PolicyInjectionBehavior>());
// Singleton registration
UnityContainer.RegisterType<TFrom, TTo>(new ContainerControlledLifetimeManager(), new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<PolicyInjectionBehavior>());
Run Code Online (Sandbox Code Playgroud)
我看不到使用该IUnityContainer.RegisterInstance()方法配置拦截的任何方法,因为它不需要任何方法InjectionMembers.如果我UnityContainer.Configure<Interception>().SetDefaultInterceptorFor<T>()在解析之前调用,我实际上可以使用实例拦截.
是否有更好/更简单的注册或嘲笑拦截器的方法?
c# unit-testing unity-container unity-interception interception