我想使用 AOP 来拦截对 ASP.NET 控制器和 ApiControllers 中所有方法的调用。
在http://structuremap.github.io/dynamic-interception/之后,我试图让它按如下方式工作。
拦截器目前并没有做太多的事情,只是提供了一种查看方法名称及其属性的方法:
public class AuthorisationInterceptor : ISyncInterceptionBehavior
{
public IMethodInvocationResult Intercept(ISyncMethodInvocation methodInvocation)
{
var classType = methodInvocation.MethodInfo.DeclaringType;
var classAttributes = classType.Attributes;
string methodName = methodInvocation.MethodInfo.Name;
var methodAttributes = methodInvocation.MethodInfo.Attributes;
//var argument = methodInvocation.GetArgument("value");
return methodInvocation.InvokeNext();
}
}
问题是如何附加它——不会出错。
我尝试了几种不同的方法,都引发了相同类型的错误..
"Decorator Interceptor failed during object construction. Specified type is not an interface,Parameter name: interfaceToProxy"
问题是 ASP.MVC 直接要求控制器(例如:“AboutController”,而不是“IAboutController”)。
public class AppCoreControllerConvention : ICustomRegistrationConvention
{
public void ScanTypes(TypeSet types, Registry registry)
{
// Attach a policy to intercept all Controllers before attaching Controllers...but it raises error.
// "Decorator Interceptor failed during object construction. Specified type is not an interface,Parameter name: interfaceToProxy"
registry.Policies.Interceptors(
new DynamicProxyInterceptorPolicy(
x => (x.IsConcrete() | !x.IsOpenGeneric()) & (x.CanBeCastTo<Controller>() | x.CanBeCastTo<ApiController>()),
new IInterceptionBehavior[]
{
new AuthorisationInterceptor(),
new AuditingInterceptor()
}
));
// Now find all Controllers/ApiControllers:
var foundControllers = types.FindTypes(
TypeClassification.Concretes | TypeClassification.Closed)
.Where(x => x.CanBeCastTo<Controller>() | x.CanBeCastTo<ApiController>())
.ToArray();
// to register them with StructureMap as themselves (ie, no 'Use' statement):
foreach (var serviceType in foundControllers)
{
registry.For(serviceType).LifecycleIs(new UniquePerRequestLifecycle());
// Although when I tried use/fore, it also raised {"Specified type is not an interface\r\nParameter name: interfaceToProxy"}
// AttachBehaviour(registry, serviceType);
}
}
//private static void AttachBehaviour(Registry registry, Type serviceType)
//{
// var dynamicProxyInterceptorType = typeof(StructureMap.DynamicInterception.DynamicProxyInterceptor<>);
// var genericDynamicProxyInterceptorType = dynamicProxyInterceptorType.MakeGenericType(new[] { serviceType });
// var interceptorBehaviors = new StructureMap.DynamicInterception.IInterceptionBehavior[]
// {
// new AuthorisationInterceptor(),
// new AuditingInterceptor()
// };
// var args = new[] { interceptorBehaviors };
// // Create
// IInterceptor interceptor =
// (StructureMap.Building.Interception.IInterceptor)Activator.CreateInstance(
// genericDynamicProxyInterceptorType,
// (BindingFlags)0,
// null,
// args,
// null);
// // Attach interceptors to Service:
// registry.For(serviceType).Use(serviceType).InterceptWith(interceptor);
//}
}
我在用着:
<package id="StructureMap" version="4.5.1" targetFramework="net461" />
<package id="StructureMap.DynamicInterception" version="1.1.1" targetFramework="net461" />
<package id="StructureMap.MVC5" version="3.1.1.134" targetFramework="net461" />
<package id="structuremap.web" version="4.0.0.315" targetFramework="net461" />
<package id="StructureMap.WebApi2" version="3.0.4.125" targetFramework="net461" />
感谢您对如何进行的任何建议。
PS:我不确定我是否完全理解https://stackoverflow.com/a/47582778/9314395的建议,但以下内容并没有神奇地产生任何拦截:
registry.For<IController>().InterceptWith(new DynamicProxyInterceptor<IController>(new IInterceptionBehavior[]{new AuthorisationInterceptor()}));