Coder Social home page Coder Social logo

ninject.extensions.interception's Introduction

Ninject

Build status codecov NuGet Version NuGet Downloads

Ninject is a lightning-fast, ultra-lightweight dependency injector for .NET applications. It helps you split your application into a collection of loosely-coupled, highly-cohesive pieces, and then glue them back together in a flexible manner. By using Ninject to support your software's architecture, your code will become easier to write, reuse, test, and modify.

Write your code so it's flexible...

public class Samurai {
    public IWeapon Weapon { get; private set; }
    public Samurai(IWeapon weapon) 
    {
        this.Weapon = weapon;
    }
}

...and let Ninject glue it together for you.

public class WarriorModule : NinjectModule
{
    public override void Load() 
    {
        this.Bind<IWeapon>().To<Sword>();
    }
}

Features:

  1. Focused. Too many existing dependency injection projects sacrifice usability for features that aren't often necessary. Each time a feature is added to Ninject, its benefit is weighed against the complexity it adds to everyday use. Our goal is to keep the barrier to entry - the baseline level of knowledge required to use Ninject - as low as possible. Ninject has many advanced features, but understanding them is not required to use the basic features.

  2. Sleek. Framework bloat is a major concern for some projects, and as such, all of Ninject's core functionality is in a single assembly with no dependencies outside the .NET base class library. This single assembly's footprint is approximately 85KB when compiled for release.

  3. Fast. Instead of relying on reflection for invocation, Ninject takes advantage of lightweight code generation in the CLR. This can result in a dramatic (8-50x) improvement in performance in many situations.

  4. Precise. Ninject helps developers get things right the first time around. Rather than relying on XML mapping files and string identifiers to wire up components, Ninject provides a robust domain-specific language. This means that Ninject takes advantage of the capabilities of the language (like type-safety) and the IDE (like IntelliSense and code completion).

  5. Agile. Ninject is designed around a component-based architecture, with customization and evolution in mind. Many facets of the system can be augmented or modified to fit the requirements of each project.

  6. Stealthy. Ninject will not invade your code. You can easily isolate the dependency on Ninject to a single assembly in your project.

  7. Powerful. Ninject includes many advanced features. For example, Ninject is the first dependency injector to support contextual binding, in which a different concrete implementation of a service may be injected depending on the context in which it is requested.

Everything else is in Extensions

Yes, sounds slim and focused, but where is the support for all the features that the competitors have?

Generally, they are maintained as specific focused extensions with owners who keep them in sync and pull in new ideas and fixes fast. These are summarized on the extensions section of the project website. Most are hosted alongside the core project right here.

License

Ninject is intended to be used in both open-source and commercial environments. To allow its use in as many situations as possible, Ninject is dual-licensed. You may choose to use Ninject under either the Apache License, Version 2.0, or the Microsoft Public License (Ms-PL). These licenses are essentially identical, but you are encouraged to evaluate both to determine which best fits your intended use.

Refer to LICENSE.txt for detailed information.

Changes history

Resources

ninject.extensions.interception's People

Contributors

chillitom avatar danielmarbach avatar giulianob avatar iappert avatar idavis avatar jamesmanning avatar ladenedge avatar oviradoi avatar remogloor avatar scott-xu avatar ursenzler avatar zach-snell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ninject.extensions.interception's Issues

Any breaking changes in latest version?

I have recently updated from Ninject 2 to Ninject 3 and have got the new version of the interception through NuGet, however one of the attribute based interception strategies I had in place is no longer working. Complaining that the IAdviceFactory is not bound to anything.

I have not changed any of the code within this area and cannot find any new documentation around any new changes etc, so was wondering if someone could possibly advise.

Here is the SO question which I wrote around the problem, which gives much more context to the issue.

http://stackoverflow.com/questions/17664220/ninject-interceptor-custom-planningstrategy-not-working-in-ninject-3

Factory and Interception

The problem appears to be an interaction or failure to interact between Ninject.Extensions.Interception and Ninject.Extensions.Factory. They work separately, but if you create an object using Factory interface and it is annotated with a C# attribute to proxy the constructed object with a proxy interceptor, it fails with an error:

2019-07-23T22:22:27.3407669Z Failed   SanityTest
2019-07-23T22:22:27.3418793Z Error Message:
2019-07-23T22:22:27.3419112Z  Initialization method MyDevice.Test.SmokeTest.TestInitialize threw exception. System.NotImplementedException: This is a DynamicProxy2 error: There are no interceptors specified for method 'ModelNameSpace.SetOfModels.ModelObject CreateModelObject()' which has no target. When calling method without target there is no implementation to 'proceed' to and it is the responsibility of the interceptor to mimic the implementation (set return value, out arguments etc).
2019-07-23T22:22:27.3419440Z Stack Trace:
2019-07-23T22:22:27.3419618Z     at Castle.DynamicProxy.AbstractInvocation.ThrowOnNoTarget()
2019-07-23T22:22:27.3419713Z    at Castle.DynamicProxy.Internal.CompositionInvocation.EnsureValidTarget()
2019-07-23T22:22:27.3419823Z    at Castle.Proxies.Invocations.IModelFactory_CreateModelObject.InvokeMethodOnTarget()
2019-07-23T22:22:27.3420072Z    at Castle.DynamicProxy.AbstractInvocation.Proceed()
2019-07-23T22:22:27.3420161Z    at Castle.Proxies.IModelFactoryProxy.CreateModelObject()
2019-07-23T22:22:27.3420473Z    at MyDevice.ConfigurationFactory.MyDeviceControl..ctor(IModelFactory ModelFactory, String dutUri) in D:\Agent_1\_work\8\s\TestToolbox\MyDevice\ConfigurationFactory\MyDeviceControl.cs:line 85
2019-07-23T22:22:27.3421003Z    at MyDevice.Test.SmokeTest.TestInitialize() in D:\Agent_1\_work\8\s\TestToolbox\MyDevice.Test\SmokeTest.cs:line 90
2019-07-23T22:22:27.3421220Z 
2019-07-23T22:22:27.3429234Z Standard Output Messages:
2019-07-23T22:22:27.3429441Z  Creating a new T-Rex Helper for URI: 'http://10.15.128.54:32011'
2019-07-23T22:22:27.3429606Z  Setting the Helper timeout to 120000 milliseconds. 

Is there some syntactic sugar to make this work? Or is this a bug? Or as yet unimplemented feature?

This is cross posted to the Factory project. It may be a team effort :), and based on the responses, I would be glad to fork and take a SWAG at it if code changes are needed..

ArgumentException when matching methods for interception

Base class of the intercepted type has a method, that is not a member of the interface that intercepted type implements. Though this method of base class it being implicitly registered for interception. I have no idea whether it is a bug or not. It worked in previous version though. Link for test project: ge.tt/4bqPYbG/v/0?c

This is for Stack Overflow question: http://stackoverflow.com/questions/10206827/ninject-interception-breaking-changes-when-porting-to-ninject-3-0

System.ArgumentException when ninject.extensions.interception module is loaded automatically

Tried Ninject.Extensions.Interception v.2, getting the following exception on the "var obj = kernel.Get();" line.

This happens only if the module is loaded automatically, i.e. the kernel is initialized with "StandardKernel kernel = new StandardKernel();"

If the module is loaded explicitly ("StandardKernel kernel = new StandardKernel(new NinjectSettings() { LoadExtensions = false }, new DynamicProxy2Module());") there's no exception and interception works fine.

System.ArgumentException was unhandled
Message="Target type for the proxy implements IProxyTargetAccessor which is a DynamicProxy infrastructure interface and you should never implement it yourself. Are you trying to proxy an existing proxy?\r\nParameter name: targetType"
Source="Castle.DynamicProxy2"
ParamName="targetType"
StackTrace:
at Castle.DynamicProxy.Generators.ClassProxyGenerator.EnsureDoesNotImplementIProxyTargetAccessor(Type type, String name)
at Castle.DynamicProxy.Generators.ClassProxyGenerator..ctor(ModuleScope scope, Type targetType)
at Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
at Ninject.Extensions.Interception.ProxyFactory.DynamicProxy2ProxyFactory.Wrap(IContext context, InstanceReference reference)
at Ninject.Extensions.Interception.Activation.Strategies.ProxyActivationStrategy.Activate(IContext context, InstanceReference reference)
at Ninject.Activation.Pipeline.<>c__DisplayClass1.b__0(IActivationStrategy s)
at Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable1 series, Action1 action)
at Ninject.Activation.Pipeline.Activate(IContext context, InstanceReference reference)
at Ninject.Activation.Context.Resolve()
at Ninject.KernelBase.b__7(IContext context)
at System.Linq.Enumerable.<>c__DisplayClass123.<CombineSelectors>b__11(TSource x) at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
at System.Linq.Enumerable.d__aa1.MoveNext() at System.Linq.Enumerable.Single[TSource](IEnumerable1 source)
at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters)
at NinjectTest.Program.Main(String[] args) in C:\dev\NinjectTest\Program.cs:line 136
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

InnerException:

How to reproduce - create C# console application and paste the code below. The code is pretty much the exact copy of one of the xunit tests with the exception of ninject kernel initialization.

using System;
using Castle.Core.Interceptor;
using Ninject;
using Ninject.Extensions.Interception;
using Ninject.Extensions.Interception.Attributes;
using Ninject.Extensions.Interception.Request;
using IInterceptor = Ninject.Extensions.Interception.IInterceptor;
using IInvocation = Ninject.Extensions.Interception.IInvocation;

//using Ninject.Extensions.Interception;

namespace NinjectTest {
public interface IFoo {
void Foo();
}

public class ObjectWithMethodInterceptor : IFoo {
    [Count]
    public virtual void Foo() {
    }
}

public class CountInterceptor : SimpleInterceptor {
    public static int Count { get; set; }

    protected override void BeforeInvoke(IInvocation invocation) {
        Count++;
    }

    public static void Reset() {
        Count = 0;
    }
}

public class CountAttribute : InterceptAttribute {
    public override IInterceptor CreateInterceptor(IProxyRequest request) {
        return request.Context.Kernel.Get<CountInterceptor>();
    }
}


internal class Program {
    private static void Main(string[] args) {
        // this doesn't work
        StandardKernel kernel = new StandardKernel();

        // this works fine
        // StandardKernel kernel = new StandardKernel(new NinjectSettings() { LoadExtensions = false }, new DynamicProxy2Module());

        kernel.Bind<IFoo>().To<ObjectWithMethodInterceptor>();
        var obj = kernel.Get<IFoo>();

        obj.Foo();
    }
}

}

AsyncInterceptor Forking Execution and Racing

I'm running into a situation where sometimes when execution passes through an async interceptor, execution splits into two threads of execution, which then race each other.

I've noticed that d84db87 introduces quite a bit of complication to async interceptors, which may be responsible for this bug, but I don't know enough about the original motivation of that change in order to surmise how the bug was introduced. From reading d84db87, it very much looks like the split execution is intentional, but that doesn't make much sense to me.

Help would be appreciated.

Castle.Core 3.3 dependency

We use Castle.Core 3.3.0.0 in our project.

TestStack.White-0.13.3 uses Castle.Core 3.3.0.0
Ninject.Extensions.Factory-3.2.1.0 uses Castle.Core 3.2.0.0
Ninject.Extensions.Interception.DynamicProxy-3.2.0.0 uses Castle.Core 3.2.0.0

Now we get a warning MSB3247 - Found conflicts between different versions of the same dependent assembly.

I think the problem is that Ninject.Extensions.Factory andNinject.Extensions.Interception.DynamicProxy does reference Castle.Core 3.2.0.0 (which has strong name. But then the nuget-dependecies is a little bit useless when VS/MSBuild have problem with this.

One workaround I've found is to use BindingRedirects but this should not be neccesary in my opinion.

Sequence contains no elements ParameterTypes.Last()

ExtensionsForMethodInfo.GetPropertyFromMethod(Type t) is throwing an exception when called on a property getter.

The method name is returned as "IGenericStateSetter`1[Boolean].get_Value", therefore the substring(0,3) does not equal "get", as expected. Since it's a property getter method.GetParameterTypes() returns an empty list, so the call to Last() throws an invalid operation exception.

I'm not trying to intercept the method, but I presume a check is being performed as to whether it should be intercepted or not.
I'm also using a Ninject.MockingKernel to create test mocks for any missing bindings. (The issue happens regardless of which mocking framework is used, I think they all use Castle.Proxies)

I don't believe there's any way to specify not to try intercepting an activation?

Stack trace:

System.Core.dll!System.Linq.Enumerable.Last<System.Type>(System.Collections.Generic.IEnumerable<System.Type> source)
Ninject.Extensions.Interception.dll!Ninject.Extensions.Interception.Infrastructure.Language.ExtensionsForMethodInfo.GetPropertyFromMethod(System.Reflection.MethodInfo method, System.Type implementingType) Line 18	
Ninject.Extensions.Interception.dll!Ninject.Extensions.Interception.Planning.Strategies.InterceptorRegistrationStrategy.Execute(Ninject.Planning.IPlan plan) Line 47	
Ninject.dll!Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map<Ninject.Planning.Strategies.IPlanningStrategy>(System.Collections.Generic.IEnumerable<Ninject.Planning.Strategies.IPlanningStrategy> series, System.Action<Ninject.Planning.Strategies.IPlanningStrategy> action)	
Ninject.dll!Ninject.Planning.Planner.CreateNewPlan(System.Type type)	
Ninject.dll!Ninject.Planning.Planner.GetPlan(System.Type type)	
Ninject.dll!Ninject.Activation.Context.ResolveInternal(object scope)	
Ninject.dll!Ninject.Activation.Context.Resolve()	
Ninject.dll!Ninject.KernelBase.Resolve(Ninject.Activation.IRequest request, bool handleMissingBindings)	
Ninject.dll!Ninject.Planning.Targets.Target<System.__Canon>.ResolveWithin(Ninject.Activation.IContext parent)	

Async Interceptor, Generic Task Raises Exception before invocation of AfterInvocation

Async interceptor does not allow AfterInvocation to handle exceptions for generic Tasks prior to throwing exceptions.

In: Ninject.Extensions.Interception/src/Ninject.Extensions.Interception/AsyncInterceptor.cs
private void InterceptTaskWithResult<TResult>(IInvocation invocation)

Invoking this:
invocationClone.ReturnValue = t.Result;

Prior to calling:

this.AfterInvoke(invocationClone);
this.AfterInvoke(invocationClone, t);

Does not allow the interceptor logic to handle the exception prior to the task throwing the AggregateExceptions.

Solution is to move AfterInvoke before assigning result:

this.AfterInvoke(invocationClone);
this.AfterInvoke(invocationClone, t);
invocationClone.ReturnValue = t.Result;

Objections?

Ninject.Extensions.Interception-3.0.0.8-release-net-3.5 build does not work correctly

I believe that the build located at: http://code.google.com/p/ninject2/downloads/detail?name=Ninject.Extensions.Interception-3.0.0.8-release-net-3.5.zip&can=2&q=Ninject.Extensions.Interception
does not work correctly.

On the contrary, building the source code of Ninject.Extensions.Interception manually, i got the exact behavior that I'm expecting and everything works as it should.

I have this piece of code:

  public class InjectorTypeService : BaseService<InjectorType>, IInjectorTypeService
    {
        [WcfExceptionInterceptor]
        public IList<InjectorTypeDto> GetAll()
        {
            IList<InjectorTypeDto> injectorTypes = new List<InjectorTypeDto>();

            using (var unitOfWork = UnitOfWorkFactory.CreateUnitOfWork())
            {
                var repo = Manager<IInjectorTypeManager>(unitOfWork);
                var results = from i in repo.GetAll() orderby i.InjectorInternalType.ToString() select i;
                foreach (var injectorType in results)
                    injectorTypes.Add(MapDto(injectorType));
            }

            return injectorTypes;
        }
  }

as you can see the method GetAll(), does not contain the keyword virtual
WcfExceptionInterceporAttribute is

public class WcfExceptionInterceptorAttribute: InterceptAttribute
    {
        // note: Interceptors are invoked in ascending order.
        private const int ORDER = 0;

        public WcfExceptionInterceptorAttribute()
        {
            this.Order = ORDER;
        }

        public override IInterceptor CreateInterceptor(IProxyRequest request)
        {
            return request.Context.Kernel.Get<LastChanceWcfExceptionHandler>();
        }
    }

and LastChanceWcfExceptionHandler just extends the SimpleInterceptor.

The problem is that if I use Ninject.Extensions.Interception.dll from your build, IInjectorTypeService returned from the Kernel is just the concrete class InjectorTypeService insted of the (correct) proxy class.
If I use the assembly Ninject.Extensions.Interception.dll from my build, it works as expected: the IInjectorTypeService returned from the Kernel is the proxyclass and the interceptor works.
The only way to make your build works, is to add again the keyword virtual to the method GetAll()..

        [WcfExceptionInterceptor]
        public virtual IList<InjectorTypeDto> GetAll()
        {
           .....
        }

As I have forked you project, here is the commit that i have used to build your source code: MiroRadenovic@cdeca34
Right now, i'm using my build with no problems.

Let me know if i can help you.

Collection modified exception

Hello,

Sometimes when starting my application I get the following error:

Collection was modified; enumeration operation may not execute.
         at System.Collections.Generic.List1.Enumerator.MoveNextRare()
         at System.Linq.Enumerable.Any[TSource](IEnumerable1 source, Func2 predicate)
         at Ninject.Extensions.Interception.Registry.AdviceRegistry.HasAdvice(IContext context) in           
         ninject.extensions.interception\src\Ninject.Extensions.Interception\Registry\AdviceRegistry.cs:line 55

This is running Ninject 2.2

I am currently refactoring my application and I am using Ninject in some places as a service locator until I have fully modified everything to be properly injected so I am using Get() quite a bit. I have read before that Ninject's create kernel is not thread safe, however, I am sharing the same kernel. It is possible it's an issue with my app but the problem did not occur until I switched to use Ninject. It also doesn't always happen and when it does it's only right when the app is first loading.

Let me know if I can provide any details or if this is probably my issue then I will do some deeper investigation.

AsyncInterceptor cannot handle exeptions

AsyncInterceptor is awesome, but it cannot handle faulted tasks.

On first glance it looks like one could override AfterInvoke(IInvocation invocation, Task task) and check the IsFaulted property of the task, but the last ContinueWith() contains this code:

invocationClone.ReturnValue = t.Result;
this.AfterInvoke(invocationClone);
this.AfterInvoke(invocationClone, t);
return (TResult)invocationClone.ReturnValue;

Thus, AfterInvoke() is only called if task.Result does not throwโ€”which it will if the task is faulted!

What I believe is needed is a check of t.IsFaulted before accessing t.Result and then calling the virtual methods appropriately.

IInterceptor not refreshing inject

Hi There,

We recently updated to the latest Ninject and Ninject extensions library. We have noticed we are now getting disposed exceptions when using the following generic transaction interceptor.

It appears even though we are running the below in request scope it is still holding onto a previous instance of the EF context and using it to try and start a new transaction. Where previously we were getting a new context instance for each request scope.

/// <summary>
/// Used to mark a method that requires being wrapped in a transaction.
/// </summary>
public class UseTransactionAttribute : InterceptAttribute
{
    private readonly IsolationLevel _isolationLevel;

    /// <summary>
    /// Initializes a new instance of the <see cref="UseTransactionAttribute"/> class.
    /// </summary>
    public UseTransactionAttribute(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
    {
        _isolationLevel = isolationLevel;
    }

    /// <summary>
    /// Create the interceptor attached to this attribute.
    /// </summary>
    /// <param name="request">The proxy request being made.</param>
    /// <returns>A <see cref="IInterceptor"/> to wrap the method in.</returns>
    public override IInterceptor CreateInterceptor(IProxyRequest request)
    {
        var isolationLevel = new ConstructorArgument("isolationLevel", _isolationLevel);
        return request.Kernel.Get<UseTransactionInterceptor>(isolationLevel);
    }
}

/// <summary>
/// Transaction method is responsible for wrapping a method in a transaction in a consistent way.
/// </summary>
public class UseTransactionInterceptor : IInterceptor
{
    private readonly IObjectContextAdapter _context;
    private readonly IsolationLevel _isolationLevel;

    /// <summary>
    /// Initializes a new instance of the <see cref="UseTransactionInterceptor"/> class.
    /// </summary>
    public UseTransactionInterceptor(IObjectContextAdapter context, IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
    {
        _context = context;
        _isolationLevel = isolationLevel;
    }

    /// <summary>
    /// Intercept the method call so it can be wrapped in a transaction. Check if a transaction is active, if it isn't start a new one otherwise do nothing as we are already in one.
    /// </summary>
    /// <param name="invocation">The invocation we are wrapping a transaction around.</param>
    public void Intercept(IInvocation invocation)
    {
        var database = ((DbContext)_context).Database;

        // Don't start another transaction if we are already in one.
        if (database.CurrentTransaction != null)
        {
            invocation.Proceed();
        }
        else
        {
            using (var transaction = database.BeginTransaction(_isolationLevel))
            {
                try
                {
                    invocation.Proceed();
                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }
        }
    }
}

If we replace the line

var database = ((DbContext)_context).Database;

with:

var t = invocation.Request.Kernel.Get<IObjectContextAdapter>();
var database = ((DbContext)t).Database;

We get the behavior we were getting before. So it appears the interceptor is being cached perhaps? Or is this an expected behavior change?

Intercept class and use the logger instance of the class

I've used Postsharp in my projects so far and now I want to replace it with Ninject Interception.
I would like to log the Execute method with interception and would like to use the same instance as ILogger . How can I best solve that writing Interception to the same log file as ExportTask.

public class Program
{
public static void Main()
{
IKernel kernel = new StandardKernel();
kernel.Bind(typeof(ILogger<>)).To(typeof(Logger<>));
kernel.Bind().ToSelf();
var task = kernel.Get();
task.Execute();
}
}

public class ExportTask
{

private ILogger<ExportTask> _logger;

public ExportTask(ILogger<ExportTask> logger)
{
	_logger = logger;
}

[Intercept]
public void Execute()
{
	//
}

}

Improvement: Interface based interception

At present interception is applied to concrete classes, in order for a class to be interceptable the class mustn't be sealed, all methods must be virtual and the class should have a default constructor. This places a number of restrictions on what can be intercepted.

It would be great if there was a way to intercept on the interface/service instead of the concrete types. I believe this should be possible as mocking libraries suchs as Moq (which also uses DynamicProxy2) and FakeItEasy perform this trick already.

Use of inherited ConstructorArguments/Parameters causes DynamicProxyProxyFactory to fail.

Use of inherited ConstructorArguments and other Parameters cause errors in intercepted classes that take constructor arguments.

Because the proxy factory doesn't perform any matching of constructor argument against the parameters list non-matching inherited parameters will cause Castle's ProxyGenerator to throw. The factory also passes all parameters to the generator not just ConstructorArguments, passing only explicit constructor arguments would probably make more sense.

System.ArgumentException : Can not instantiate proxy of class:      Ninject.Extensions.Interception.DynamicProxyProxyFactoryTests+ClassWithConstructorArgs.
   Could not find a constructor that would match given arguments:
   System.String
   Parameter name: constructorArguments

   Stack Trace:
      at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyInstance(Type proxyType, List`1 proxyArguments, Type classToProxy, Object[] constructorArguments)
      at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)   
      at Ninject.Extensions.Interception.ProxyFactory.DynamicProxyProxyFactory.Wrap(IContext context, InstanceReference reference) 
      at Ninject.Extensions.Interception.Activation.Strategies.ProxyActivationStrategy.Activate(IContext context, InstanceReference reference)
      at Ninject.Activation.Pipeline.<>c__DisplayClass2.<Activate>b__0(IActivationStrategy s) 
      at Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable`1 series, Action`1 action)     
      at Ninject.Activation.Pipeline.Activate(IContext context, InstanceReference reference)
      at Ninject.Activation.Context.Resolve()
      at Ninject.KernelBase.<>c__DisplayClass13.<Resolve>b__f(IBinding binding)
      at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()

A quick and rather rough fix might be to filter out all inherited parameters, a full fix might involve using Ninject's constructor scoring and picking constructor arguments from the parameters list.

Will dig in a little more.

I cann't inject into ILog with interception

Binding:
IKernel kernel = new StandardKernel();
kernel.Bind().ToMethod(context => LogManager.GetLogger(context.Request.Target.Type));
kernel.Bind().ToSelf().Intercept().With();
ISyncService syncService = kernel.Get();
Consumption:
public class TSyncService:ISyncService
{
ILog log;
public TSyncService(ILog log)
{
this.log = log;
}

Error:
An unhandled exception of type 'Castle.DynamicProxy.InvalidProxyConstructorArgumentsException' occurred in Castle.Core.dll

Additional information: Can not instantiate proxy of class: SSHZ.PRIS.Test.WinService.TSyncService.
Could not find a parameterless constructor.

Performance Issues with Interceptors

I am using an Interceptor in my app for Logging (Method Start, Method End);
There are some filtering methods which are called very often in the application.

If i am using Interceptors i have enormous performance leaks. Turning the interceptors of its very fast.

image

Ninject.Extensions.Interception.Registry.AdviceRegistry.GetInterceptors(IProxyRequest)
-> Ninject.Extensions.Interception.Registry.AdviceRegistry.GetInterceptorsForRequest(IProxyRequest)
-> System.Linq.Enumerable+SelectListIterator`2.ToList()

The more methods called, the slower the overall performance.

InterceptAttributeBase should allow AttributeTargets.Property

I'm trying to apply an aspect to a property. Unfortunately InterceptAttributeBase lists only class and method as targets.

I have locally added property as an addtional target as follows:

[AttributeUsage( AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true, Inherited = true )]
public abstract class InterceptAttributeBase : Attribute
{
   // ... remainder of implementation left out for brevity

With this change interception based on attributes now also works for properties which is not surprising as the class DynamicMethodFactory has already members for creating property getters and setters.

Can I ask to include this suggested change into the code base? Thank you!

System.InvalidOperationException when intercepting method with same signature aside from type params

When I'm trying to intercept a call to a method that has an identical signature to another except for type parameters I get a System.InvalidOperationException. I'm not sure from the documentation whether this behavior is expected or not. Running the following test gives me this result:

Result StackTrace:	
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
   at Ninject.Extensions.Interception.Advice.Advice.MatchesMethodPredicate(IProxyRequest request)
   at Ninject.Extensions.Interception.Advice.Advice.Matches(IProxyRequest request)
   at Ninject.Extensions.Interception.Registry.AdviceRegistry.<>c__DisplayClass10_0.<GetInterceptorsForRequest>b__0(IAdvice advice)
   at System.Linq.Enumerable.WhereListIterator`1.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](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 Castle.Proxies.IInterceptedClassProxy.DoSomething()
   at InterceptorTest.ParameterTest.TestTypeParameters() in ...\InterceptorTest\InterceptorTest\ParameterTest.cs:line 58
Result Message:	System.InvalidOperationException : Sequence contains more than one matching element
using Ninject;
using Ninject.Extensions.Conventions;
using Ninject.Extensions.Interception;
using Ninject.Extensions.Interception.Infrastructure.Language;
using NUnit.Framework;
using System;

namespace InterceptorTest
{
    public interface IInterceptedClass
    {
        object DoSomething();
        T DoSomething<T>();
    }

    public class InterceptedClass : IInterceptedClass
    {
        public object DoSomething()
        {
            return null;
        }

        public T DoSomething<T>()
        {
            return default(T);
        }
    }

    public class TestInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            Console.WriteLine("interceptor before call");

            invocation.Proceed();

            Console.WriteLine("interceptor after call");
        }
    }

    [TestFixture]
    public class ParameterTest
    {
        [Test]
        public void TestTypeParameters()
        {
            var kernel = new StandardKernel();
            kernel.Bind(x =>
                x.FromThisAssembly()
                    .SelectAllClasses()
                    .BindDefaultInterface()
                    .Configure(y => y
                        .Intercept()
                        .With<TestInterceptor>())
            );

            kernel.Get<IInterceptedClass>().DoSomething();
        }
    }
}

Proper usage of AutoNotifyPropertyChangedInterceptor

Hi. How do we set up the binding for AutoNotifyPropertyChangedInterceptor in a custom module? What I have tried so far:

public class MyViewModel : IMyViewModel {
virtual properties and methods marked with [NotifyOfChanges] attribute
public void OnPropertyChanged
}

public IMyViewModel : IAutoPropertyChanged {
}

*My custom module

public class MyModule : NinjectModule {

Bind(typeof(AutoNotifyPropertyChangedInterceptor<>)).ToSelf() - not working
Bind(typeof(IAutoNotifyPropertyChangedIntercertor<>).To(typeof(AutoNotifyPropertyChangedInterceptor<>)(); - not working
.
.
ViewModel binding works without problems

also, what is correct intercept binding method on the ViewModel itself?

binding.Intercept().With<AutoNotifyPropertyChangedInterceptor>().InOrder(1);
...some other interceptor in chain

or

binding.Intercept().With<IAutoNotifyPropertyChangedInterceptor>
.InOrder(1);
...some other interceptor in chain

I have tried both approaches (binding to interface and concrete type) but it throws an exception during kernel build. Should I use InterceptAttribute for this interceptor instead of binding in a module ?

Any help would be appreciated. Thanks.

Interface not found

Hi,

i'm using the current version from nuget with LinFu and i get a "Interface not found" exception from .net/ninject.

My example:

public interface IUserRepository : IBaseRepository<User, long>
{
IList FindByParameters(string loginName, string email, string name);
}

public class UserRepository : BaseRepository<User, long>, IUserRepository
{
public virtual IList FindByParameters(string loginName, string email, string name)
{
....
}
}

How i register all my classes:

kernel.Bind(scanner => scanner.FromAssembliesMatching("XXX.*")
.SelectAllClasses()
.BindDefaultInterfaces()
.Configure(cfg => cfg.InRequestScope()));

If i inject the IUserRepository in my page, the call on methods from the I/BaseRepository works fine (also with my own transactional interceptor) but if i call FindByParameters, i get the "Interface not found" exception.

Is there any workaround availabe?
Inject the class instead of the interface works fine but thats no good solution.

Thanks.

Intercepting methods called from within own class?

I am not sure if this is a bug or not, but I have a class like so in a console app example:

public class SaySomethingAction : IAction
    {
        public virtual void Run()
        {
            Console.WriteLine("Type in what you want to say, then press enter");
            var message = Console.ReadLine();

            Say(message);
        }

        [DelayFor(2)]
        public virtual void Say(string message)
        {
            Console.WriteLine($"Saying {message}");
        }
    }

So my expectations is that when the Run method invokes Say it would trigger the DelayFor attribute (which is an InterceptAttribute), which would in turn call through to the relevant interceptor. However the interceptor associated with that attribute is not fired on Say, however if I were to put the [DelayFor(2)] onto the Run method, that WOULD correctly trigger and proxy the method.

So is this use case supported?

Assembly binding issue within dynamic proxy

I have the following DLL dependencies. Main.dll uses Contract.dll version 1.0.0.1
Main.dll also uses Client.dll , Client.dll uses contract.dll version 1.0.0.0

Main.dll uses windsor container to get a service defined in Client.dll (interceptors registered to container for logging) and invoked a method on it, passing a parameter, the type of which is defined in Contract.dll.

//Message.class in Contract.dll
var message = new Message("some context dependent text")

//IService defined in Client.dll

var service = container.Get();
service.DoSomething(message)

I get this error

Could not load file or assembly 'Contract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. A strongly-named assembly is required.

The dll available during runtime is version 1.0.0.1 and none of the dll(s) involved are strongly named so the usual case of a signed assembly using an unsigned assembly can be ruled out.

But I will assume as the public interfaces are identical, this should have worked.

The version of castlle.core and windsor used is 2.5.1 and I am currently unable to move to newer versions in the near future.

Unable to cast exception on Injection with Dynamic Proxy and Interface Inheritance

I have ran into an issue when binding two interfaces to the same concrete class when there is an Interceptor on the singleton binding.
Without the Interceptor these tests will all pass because when InterfaceA or InterfaceB is injected it is injected as the concrete class type. However with the interceptors it puts Castle.Proxies.InterfaceAProxy Or Castle.Proxies.InterfaceBProxy purely dependent upon which Kernel.Get was called first. Since InterfaceA inherits from InterfaceB, when InterfaceA goes first it can cast as the proxy for InterfaceB. But it will not work the other way around.

I have taken the complexity out of the instance I ran into and put it into a very basic scenario below. To run this snippet create a UnitTest Project in VisualStudio and add the Ninject.Extensions.Interception.DynamicProxy NuGet Package v3.3.3.

    public class Interceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            //Interceptor Logic
        }
    }

    public interface InterfaceB
    {
        //Definition
    }
    public interface InterfaceA : InterfaceB
    {
        //Definition
    }
    public class Implementation : InterfaceA
    {
        //Logic
    }

    public class BusinessLogic_One
    {
        private readonly InterfaceA _interface;
        public BusinessLogic_One(InterfaceA input)
        {
            _interface = input;
        }
    }

    public class BusinessLogic_Two
    {
        private readonly InterfaceB _interface;
        public BusinessLogic_Two(InterfaceB input)
        {
            _interface = input;
        }
    }

    [TestClass]
    public class UnitTests
    {
        private IKernel _kernel;
        [TestInitialize]
        public void TestInit()
        {
            _kernel = new StandardKernel();

           //If the Intercept().With<Interceptor>() is commented out all tests will pass.
            _kernel.Bind<InterfaceA, InterfaceB>().To<Implementation>().InSingletonScope()
                .Intercept().With<Interceptor>();
            _kernel.Bind<BusinessLogic_One>().ToSelf().InSingletonScope();
            _kernel.Bind<BusinessLogic_Two>().ToSelf().InSingletonScope();
        }

         
        [TestMethod]//Test Passes
        public void Test_Calling_KernelGet_InterfaceAFirst()
        {
            var bl1 = _kernel.Get<BusinessLogic_One>();//InterfaceA
            var bl2 = _kernel.Get<BusinessLogic_Two>();//InterfaceB
        }

        [TestMethod]//Test Fails
        public void Test_Calling_KernelGet_InterfaceBFirst()
        {
            var bl2 = _kernel.Get<BusinessLogic_Two>();//InterfaceB
            var bl1 = _kernel.Get<BusinessLogic_One>();//InterfaceA
        }
    }

The Exception I get on the Failed test is:
Message: Test method UnitTests.Test_Calling_KernelGet_InterfaceBFirst threw exception:
System.InvalidCastException: Unable to cast object of type 'Castle.Proxies.InterfaceBProxy' to type 'InterfaceA'.

Would it be possible in the next version for this to be a Castle.Proxies.ImplementationProxy or something that both interfaces could inherit from?

Not sure why this is failing ...

Tried:

Implementing Ninject.Extensions.Interception.IInterceptor, easy enough called 'InstrumentationInterceptor'.

public class InstrumentationInterceptor : IInterceptor
	{
		private static readonly ILog Log;

		static InstrumentationInterceptor()
		{
			Log = new RepositoryLoggingService().GetLogger(typeof(InstrumentationInterceptor));
		}

		private T TimeWrap<T>(string message, Func<T> function)
		{
			var stopWatch = Stopwatch.StartNew();

			var result = function();

			stopWatch.Stop();

			Log.Info($"{message}::{stopWatch.ElapsedMilliseconds}ms");

			return result;
		}

		public void Intercept(IInvocation invocation)
		{
			var message = $"Connect.Repository.Instrumentation -> {MethodSignatureFormatter.GetSignature(invocation.Request.Method, invocation.Request.Arguments)}";

			TimeWrap(message, () =>
			{
				invocation.Proceed();

				return invocation.ReturnValue;
			});
		}
	}

Then registering with:

Kernel.Bind<InstrumentationInterceptor>().ToSelf().InSingletonScope();

 Kernel.Bind(x => x
                .From(GetType().Assembly)
                .SelectAllClasses()
                .InNamespaceOf(GetType())
                .BindAllInterfaces()
				.Configure(c => c.Intercept(
					typeof(InstrumentationInterceptor),
					typeof(DatabaseWinsConcurrencyInterceptor))));


Ended up with:

[NullReferenceException]: Object reference not set to an instance of an object.
at Ninject.Extensions.Interception.Advice.Advice.GetInterceptor(IProxyRequest request)
at System.Linq.Enumerable.WhereSelectListIterator2.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 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 Castle.Proxies.IAuthenticationRepositoryProxy.FindUser(String userName, String password)

Not compatible with Castle.Core 4.4.0

I get the compiler error:

Message: System.TypeLoadException : Method 'CaptureProceedInfo' in type 'Ninject.Extensions.Interception.ProxyFactory.ObjectMethodsInvocation' from assembly 'Ninject.Extensions.Interception.DynamicProxy, Version=3.3.3.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7' does not have an implementation.

I tracked it down to ObjectMethodsInvocation which inherits from IInvocation which now requires implementation of CaptureProceedInfo.

class proxy (apicontroller) and constructor args

I have read in historical articles/tickets/posts that if you want to do proxying on classes you need to provide a parameterless constructor. I was just wondering is this still applicable, and if so is it a problem within the ninject layer or castle dynamic proxy layer?

As if I have a class like:

public class SomeClassToProxy
{
   public SomeClasstoProxy(ISomething something) { ... }

   [SomeInterceptAttribute]
   public virtual DoSomething() { ... }
   
}

And lets assume somewhere I have Bind<ISomething>().To<Something>();, so the DI framework knows about the ISomething and how to resolve it, so when it says it needs a parameterless constructor I am unsure why it causes a problem when I am binding against the class opposed to the interface, as even if I proxy against an interface (i.e. public class SomeClassToProxy : ISomeInterfaceToProxy) and have the binding at the interface layer it still needs to resolve the SomeClassToProxy at some point.

Anyway some info around this issue would be great as atm the moment we try to put any intercept attributes on an ApiController DynamicProxy blows up because it cannot find a parameterless constructor.

Intercepting methods with ref and out parameters

It appears that the newest set of sources does not support methods with ref or out parameters, e.g. trying to intercept the following will fail with VerificationException in certain scenarios (at least the ones I tested):

public virtual void Foo(ref Guid guid) { ... }

By the same token the following can be intercepted:

public virtual void Foo(Guid guid) { ... }

With code modification in DynamicMethodFactory.CreateInvoker() using example code from downloadable source code at http://www.codeproject.com/KB/cs/FastMethodInvoker.aspx?msg=2523854
the above can be correctly intercepted for both ref and out parameters.

Are there any plans to add support for ref and out parameters to Ninject.Extensions.Interception? It appears as if none of the examples (e.g. tests) in this project use ref or out parameters. Without this support this limits the set of signatures that can be used for methods that can be intercepted.

Interception of inherited methods (e.g. GetHashCode)

I use master on production because of #26 (thanks again) and I encountered another problem with method interceptors applied manually e.g.:

kernel.Bind<IBar>().To<Bar>().Intercept().With<MethodInterceptor>();

They intercept not only public methods of Bar, but also inherited (Equals/GetHashCode). It's not the case when interception is applied via InterceptAttribute. And it's also differs from "official" 3.0.0.8 NuGet package.

See full example here:

https://gist.github.com/orient-man/9625459

In my use case this leads to large performance penalty. I'm not sure if this change is intentional.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.