多年来我一直在努力想到这一点.当我尝试用拦截器绑定我的类时,我在行上得到以下异常
Kernel.Bind<MyClass>().ToSelf().Intercept().With<ILoggerAspect>();
Run Code Online (Sandbox Code Playgroud)
加载Ninject组件IAdviceFactory时出错.没有这样的组件已在内核的组件容器中注册
我已尝试使用和不使用LoadExtensions,使用模块来设置我的绑定,我的上次尝试看起来像这样
internal class AppConfiguration
{
internal AppConfiguration( )
{
var settings = new NinjectSettings() { LoadExtensions = false };
Kernel = new StandardKernel(settings);
Load();
}
internal StandardKernel Kernel { get; set; }
public static AppConfiguration Instance
{
get { return _instance ?? (_instance = new AppConfiguration()); }
}
private static AppConfiguration _instance;
private void Load()
{
Kernel.Bind<ILoggerAspect>().To<Log4NetAspect>().InSingletonScope();
Kernel.Bind<MyClass>().ToSelf().Intercept().With<ILoggerAspect>();
}
internal static StandardKernel Resolver()
{
return Instance.Kernel;
}
}
Run Code Online (Sandbox Code Playgroud)
我的记录器属性看起来像这样
public class LogAttribute : InterceptAttribute
{
public override …Run Code Online (Sandbox Code Playgroud) 每次调用ASP.NET WebApi控制器的一个操作方法时,我们公司都需要记录某些内容.由于我们现在使用Ninject作为DI,我们也想将它用于此目的.这是我到目前为止所尝试的.
我有通过NuGet安装的Ninject,Ninject.Extensions.Interception和Ninject.Extensions.Interception.DynamicProxy,我有以下模块
public class InterceptAllModule : InterceptionModule
{
public override void Load()
{
Kernel.Intercept(p => p.Request.Service.Name.EndsWith("Controller")).With(new TimingInterceptor());
}
}
Run Code Online (Sandbox Code Playgroud)
TimingInterceptor的位置
public class TimingInterceptor : SimpleInterceptor
{
readonly Stopwatch _stopwatch = new Stopwatch();
protected override void BeforeInvoke(IInvocation invocation)
{
_stopwatch.Start();
}
protected override void AfterInvoke(IInvocation invocation)
{
_stopwatch.Stop();
string message = string.Format("[Execution of {0} took {1}.]",invocation.Request.Method,_stopwatch.Elapsed);
Log.Info(message + "\n");
_stopwatch.Reset();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当我尝试使用ninject内核挂起模块时,运行我的站点
var kernel = new StandardKernel(new InterceptAllModule());
Run Code Online (Sandbox Code Playgroud)
但是,只要有一个调用进入其中一个操作方法,它就会抛出一个错误说
Cannot instantiate proxy of class: MyApiController.
Run Code Online (Sandbox Code Playgroud)
有经验的人可以指出我做错了吗?谢谢.
asp.net-mvc logging ninject ninject-interception asp.net-web-api
我如何获得Ninject.Extensions.Interception基本上让我将特定的拦截器绑定到任何具有属性的方法... psudocode:
Kernel.Intercept(context => context.Binding.HasAttribute<TransactionAttribute>())
.With<TransactionInterceptor>
Run Code Online (Sandbox Code Playgroud)
有一个类:
public SomeClass
{
[TransactionAttribute]
public void SomeTransactedMethod()
{ /*do stuff */ }
}
Run Code Online (Sandbox Code Playgroud) 我已经注意到在截取教程中你可以定位一个方法并拦截它.即
Kernel.Bind<Foo>().ToSelf();
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(), invocation => {} );
Run Code Online (Sandbox Code Playgroud)
文档/教程没有介绍在您尝试拦截的方法具有参数的实例中要执行的操作,即ThrowsAnError是否接受字符串作为参数.
Kernel.Bind<Foo>().ToSelf();
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(**param goes here**), invocation => {} );
Run Code Online (Sandbox Code Playgroud)
在绑定时我无法访问params,所以我想知道我是否会以错误的方式进行此操作?
编辑
c# dependency-injection ninject ninject-extensions ninject-interception
假设我有一个类,我希望有时*(但现在总是)拦截一些(但不是全部)方法.我理解它的方式,可以InterceptAround()在我的Ninject模块(在更高级别的代码中)或者在这些方法上(在实现级别)使用InterceptAttribute派生的属性来完成.
我真的不喜欢第一种方式,因为它需要消费者知道细节,有很多类有很多方法.但我也不喜欢第二种方式,因为我没有看到如何禁用(或者更确切地说,不启用)拦截,因为属性与代码融合.
有没有一些已知的方法来解决这个问题?
*:适用于应用程序的生命周期.
我会形容我的环境:我有Ninject + Ninject拦截扩展合作,以使所有的方法,标有特殊属性的拦截器自动注册.这是一个常见的AoP +属性+ DI容器场景.
我的问题是:当移植到Ninject和Ninject拦截扩展的最新版本 - 3.0我开始变得异常时,我的拦截器应该运行.我的InterceptorRegistrationStrategy在解析属性类型和注册拦截器时工作正常.但运行截获的方法会导致以下异常:
System.ArgumentException : Interface not found.
at System.RuntimeTypeHandle.VerifyInterfaceIsImplemented(RuntimeTypeHandle handle, RuntimeTypeHandle interfaceHandle)
at System.RuntimeType.GetInterfaceMap(Type ifaceType)
at Ninject.Extensions.Interception.Advice.Advice.MatchesMethod(IProxyRequest request)
at System.Linq.Enumerable.WhereListIterator`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList(IEnumerable`1 source)
at Ninject.Extensions.Interception.Registry.AdviceRegistry.GetInterceptorsForRequest(IProxyRequest request)
at Ninject.Extensions.Interception.Registry.AdviceRegistry.GetInterceptors(IProxyRequest request)
at Ninject.Extensions.Interception.Wrapper.StandardWrapper.CreateInvocation(IProxyRequest request)
at Ninject.Extensions.Interception.Wrapper.DynamicProxyWrapper.Intercept(IInvocation castleInvocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Infrastructure.Tests.Persistance.Conversations.NinjectConversationInterceptorBehavior.ShouldCreateInterceptorOnImplicitConversation() in NinjectConversationInterceptorBehavior.cs: line 74
Run Code Online (Sandbox Code Playgroud)
我有点左诉诸反射器,并使用Ninject拦截扩展来源做些什么这个问题,没有足够的文档,它让我在一个糟糕的位置配对.
移植到Ninject 3.0时,任何人都有同样的例外吗?
这是我用来根据属性自动注册拦截器的代码:
public class NinjectConversationInterceptorRegistrationStrategy : InterceptorRegistrationStrategy
{
public NinjectConversationInterceptorRegistrationStrategy(IAdviceFactory adviceFactory,
IAdviceRegistry adviceRegistry)
: base(adviceFactory, adviceRegistry)
{
}
public override void Execute(IPlan plan)
{
var pcAttribute …Run Code Online (Sandbox Code Playgroud) aop ninject interceptor ninject-extensions ninject-interception
我正在学习使用Ninject和Interceptor模式.
我有以下拦截器.
public class MyInterceptor:IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("Pre Execute: " + invocation.Request.Method.Name);
foreach (var param in invocation.Request.Arguments)
{
Console.WriteLine("param : " + param);
}
invocation.Proceed();
Console.WriteLine("Post Execute: " + invocation.Request.Method.Name);
Console.WriteLine("Returned: " + invocation.ReturnValue);
}
}
Run Code Online (Sandbox Code Playgroud)
并且有一个名为MyClass只有2个简单方法的类,虚拟允许拦截器处理它们.(两种方法是Echo和double,这就像他们的名字所说的那样.)
我通过NuGet将Ninject,Ninject.Extensions.Interception和Ninject.Extensions.Interception.DynamicProxy添加到我的项目中.
添加以下using声明.
using Ninject;
using Ninject.Extensions.Interception.Infrastructure.Language;
using Ninject.Extensions.Interception;
Run Code Online (Sandbox Code Playgroud)
我的Main方法,它执行引导看起来像这样.
static void Main(string[] args)
{
MyClass o = null;
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<MyClass>().ToSelf().Intercept().With(new MyInterceptor());
o = kernel.Get<MyClass>();
}
o.Echo("Hello World!"); // Error …Run Code Online (Sandbox Code Playgroud) c# ninject castle-dynamicproxy ninject-extensions ninject-interception
我开始使用ninject拦截器来处理我的一些异步代码以及各种行为,并且在使一切正常工作时遇到一些麻烦.
这是我正在使用的拦截器:
public class MyInterceptor : IInterceptor
{
public async void Intercept(IInvocation invocation)
{
try
{
invocation.Proceed();
//check that method indeed returns Task
await (Task) invocation.ReturnValue;
RecordSuccess();
}
catch (Exception)
{
RecordError();
invocation.ReturnValue = _defaultValue;
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
在大多数正常情况下,这似乎可以正常运行.我不确定这是否符合我的预期.虽然它似乎异步地将控制流返回给调用者,但我仍然有点担心代理无意中阻塞某个线程或其他东西.
除此之外,我无法让异常处理工作.对于此测试用例:
[Test]
public void ExceptionThrown()
{
try
{
var interceptor = new MyInterceptor(DefaultValue);
var invocation = new Mock<IInvocation>();
invocation.Setup(x => x.Proceed()).Throws<InvalidOperationException>();
interceptor.Intercept(invocation.Object);
}
catch (Exception e)
{
}
}
Run Code Online (Sandbox Code Playgroud)
我可以在拦截器中看到catch块被击中,但我的测试中的catch块从未被重新抛出.我更困惑,因为这里没有代理或任何东西,只是非常简单的模拟和对象.我也尝试了类似于Task.Run(() => interceptor.Intercept(invocation.Object)).Wait();我的测试,但仍然没有变化.测试通过愉快,但nUnit输出确实有异常消息.
我想我搞砸了一些东西,而且我不太清楚我认为发生了什么.是否有更好的方法来拦截异步方法?关于异常处理,我做错了什么?
我有一个NinjectWebCommon如下.我无法让TimingInterceptor在具有"Timing"属性集的方法上触发.如果拦截器是在类级别定义的,其中所有方法调用都将被截获,它可以正常工作,但我希望能够指定我想拦截的方法(选择加入).
我确实添加了Ninject.Extensions.Interception.DynamicProxy.
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var NinjectSettings = new NinjectSettings();
var kernel = new …Run Code Online (Sandbox Code Playgroud) 我正在使用Ninject Interceptor,以便在调用实际方法之前和之后执行某些任务,但我需要这些操作是异步的.我看一下下面的文章make-ninject-interceptors-work-with-async-methods并实现异步部分,但现在我错过了最后一篇文章,那就是等待/非阻塞等待任务完成在拦截方法中.
我不能使用wait因为我希望这是异步非阻塞操作
/// <summary>
/// Intercepts the specified invocation.
/// </summary>
/// <param name="invocation">The invocation to intercept.</param>
public void Intercept(IInvocation invocation)
{
Task<bool> resultTask = InterceptAsync(invocation);
if (resultTask.Exception != null)
throw new Exception("Exception.", resultTask.Exception.InnerException);
}
/// <summary>
/// Intercepts the specified invocation.
/// </summary>
/// <param name="invocation">The invocation to intercept.</param>
protected async Task<bool> InterceptAsync(IMyInvocation invocation)
{
await BeforeInvokeAsync(invocation);
if (!invocation.Cancel)
{
invocation.Proceed();
await AfterInvokeAsync(invocation);
}
return true;
}
Run Code Online (Sandbox Code Playgroud)我甚至试图将async放在这个方法上,但我仍然遇到问题,可能是因为这是一个void方法
/// <summary>
/// Intercepts the specified invocation.
/// …Run Code Online (Sandbox Code Playgroud)我正在使用Ninject和AOP来做一些缓存.我有一个属性,我可以应用于我的存储库中的任何方法和BeforeInvoke它将返回我的缓存对象,如果有一个和AfterInvoke创建一个缓存的对象.这一切都很好,但我无法弄清楚如何停止调用初始方法,即如果有一个缓存的对象返回而不是调用intyercepted方法.我的拦截器在这里:
public class CacheInterceptor : SimpleInterceptor
{
protected override void BeforeInvoke(IInvocation invocation)
{
Type returnType = invocation.Request.Method.ReturnType;
string cacheKey = CacheKeyBuilder.GetCacheKey(invocation, serializer);
object cachedValue = cache.Get(cacheKey);
if (cachedValue == null)
{
invocation.Proceed();
}
else
{
object returnValue = serializer.Deserialize(returnType, cachedValue);
invocation.ReturnValue = returnValue;
returnedCachedResult = true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
即使在else语句中我显然没有说要调用被调用的方法'invocation.Proceed();' 它仍然会调用它.如何告诉ninject只返回invocation.ReturnValue?
ninject ×10
c# ×7
aop ×5
.net ×2
async-await ×2
asp.net-mvc ×1
interception ×1
interceptor ×1
logging ×1