Giter Club home page Giter Club logo

autofac.extras.dynamicproxy's Introduction

Autofac.Extras.DynamicProxy

Interceptor and decorator support for Autofac via Castle DynamicProxy.

Build status codecov

Autofac on Stack Overflow

Get Packages

You can get Autofac.Extras.DynamicProxy by grabbing the latest NuGet packages. If you're feeling adventurous, continuous integration builds are on MyGet.

Release notes are available on GitHub.

Get Help

Need help with Autofac? We have a documentation site as well as API documentation. We're ready to answer your questions on Stack Overflow or check out the discussion forum.

If you find a bug with Autofac.Extras.DynamicProxy please file it in that repo.

Get Started

First, create your interceptor:

public class CallLogger : IInterceptor
{
  TextWriter _output;

  public CallLogger(TextWriter output)
  {
    _output = output;
  }

  public void Intercept(IInvocation invocation)
  {
    _output.Write("Calling method {0}.", invocation.Method.Name);
    invocation.Proceed();
    _output.WriteLine("Done: result was {0}.", invocation.ReturnValue);
  }
}

Then register your type to be intercepted:

var builder = new ContainerBuilder();
builder.RegisterType<SomeType>()
       .As<ISomeInterface>()
       .EnableInterfaceInterceptors();
builder.Register(c => new CallLogger(Console.Out));
var container = builder.Build();
var willBeIntercepted = container.Resolve<ISomeInterface>();

You can read more details in the documentation.

Contributing / Pull Requests

Refer to the Contributor Guide for setting up and building Autofac source.

You can also open this repository right now in VS Code.

autofac.extras.dynamicproxy's People

Contributors

alexmg avatar alistairjevans avatar alsami avatar ivanferic avatar jafin avatar raymondhuy avatar shiftkey avatar sstassen-wowcorp avatar tillig 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  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  avatar  avatar

autofac.extras.dynamicproxy's Issues

Why isn't DynamicProxy referencing newer Versions of AutoFac

My Problem is that Autofac up to 4.0.1 has a severe bug which is autofac/Autofac#789 . But unfortunatley this bug is fixed only in the following versions which are not supported by DynamicProxy so I'm stuck with Autofac 4.0.1 and this bug if I want to use DynmicProxy.

So is there any reason why Dynamic Proxy is still referencing the old Version of AutoFac?

Support for version 4.0

Hi, what are the plans on releasing version 4.0 of DynamicProxy, which would work with Autofac 4.0?

Class Interceptors are not working with .NET 6

Class Interceptors with .NET 6

I am trying to implement simple class interceptors for ASP.NET 6 WebApi. I had the same code previously in .NET core 3.1 and it was working. With .NET 6, class interceptors are not working for controller methods despite marking them as virtual. Is there anything I am missing or configuring wrong? It is only an issue with class interceptors (even if I decorate class with Intercept attribute). Interface interceptors are working fine.

Steps to Reproduce

  1. Create a simple web api (.NET 6) with just a weather controller.
  2. Added packages ( Autofac 6.4.0, Autofac.Extension.DependencyInjection 8.0.0, Autofac.Extras.DynamicProxy 6.0.1, Castle.Core.AsyncInterceptor 2.1.0) and configured startup.cs class to register dependencies with Autofac container.

Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())
    .ConfigureServices((context, services) =>
    {
        services.AddControllers();
        services.AddEndpointsApiExplorer();
        services.AddSwaggerGen();
    })
    .ConfigureContainer<ContainerBuilder>(autofacBuilder =>
    {
        autofacBuilder.RegisterType<MethodExecutionMetricsLoggerAspect>();
        autofacBuilder.RegisterType<WeatherForecastController>()
            .EnableClassInterceptors().InterceptedBy(typeof(MethodExecutionMetricsLoggerAspect));
    });

var app = builder.Build();

MethodExecutionMetricsLoggerAspect

    public class MethodExecutionMetricsLoggerAspect : IInterceptor
    {
        public MethodExecutionMetricsLoggerAspect()
        {

        }
   
        public void Intercept(IInvocation invocation)
        {
            Debug.WriteLine("Inside interceptor");
            invocation.Proceed();
        }
    }

WeatherController endpoint

   public virtual IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }

Expected Behavior

Call to above method should be intercepted by MethodExecutionMetricsLoggerAspect class.
This was working fine in .NET core 3.1 but I cannot get it to work in .NET 6.

Dependency Versions

Autofac: 6.4.0
Autofac.Extension.DependencyInjection: 8.0.0
Autofac.Extras.DynamicProxy: 6.0.1
Castle.Core.AsyncInterceptor: 2.1.0

Additional Info

Cannot interface-proxy `internal` interface

Cannot interface-propxy internal interface even though assembly is marked with

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

as stated in the Documentation

Container Configuration

builder.RegisterType<TrackCurrentSingleCallInterceptor>().AsSelf();

builder.RegisterType<SingleCall>()
    .As<ISingleCallWithUpdate>()
    .EnableInterfaceInterceptors()
    .InterceptedBy(typeof(TrackCurrentSingleCallInterceptor));

Exception

System.InvalidOperationExceptionThe component Activator = SingleCall (ReflectionActivator), Services = [Pmr.TetrapolRadio.SingleCommunication.ISingleCallWithUpdate], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope cannot use interface interception as it provides services that are not publicly visible interfaces. Check your registration of the component to ensure you're not enabling interception and registering it as an internal/private interface type.
at Autofac.Extras.DynamicProxy2.RegistrationExtensions.EnsureInterfaceInterceptionApplies(IComponentRegistration componentRegistration)
at Autofac.Extras.DynamicProxy2.RegistrationExtensions.<>c__DisplayClassc3.<EnableInterfaceInterceptors>b__9(Object sender, ActivatingEventArgs1 e)
at System.EventHandler1.Invoke(Object sender, TEventArgs e) at Autofac.Core.Registration.ComponentRegistration.RaiseActivating(IComponentContext context, IEnumerable1 parameters, ref Object instance)
at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1 parameters) at Autofac.Core.Resolving.InstanceLookup.Execute() at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable1 parameters)
at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)

(Hint: Moq-ing internal interfaces from the same assembly works (=> in a different test assembly), so the attribute is set correctly).

Issue-Analysis

RegistrationExtensions.EnsureInterfaceInterceptionApplies contains a check

if (((Type) swt.ServiceType).IsInterface)
          return !((Type) swt.ServiceType).IsVisible;

This check is not in line with documentation, because IsVisible only returns true if the type is public, not when it's internal combined with InternalsVisibleToAttribute.

I don't think that there's a possiblity to check for whether some Type is visible to another Assembly due to InternalsVisibleToAttribute, so i suggest just getting rid of the IsVisible check.

Comment: As the exception is occuring during resolving (not when building the container), the failure-case will still be detected at the exact same time. Only potential downside is, that Castle DynamicProxy's exception message might not be as verbose. In one part it's more verbose, however, because it states that you can fix it by adding an InternalsVisibleToAttribute...

Interface interception fails when used with open generic assembly scanning

This comes from a StackOverflow question

Using assembly scanning in conjunction with interface interception yields an exception:

The component ... cannot use interface interception as it provides services that are not publicly visible interfaces. Check your registration of the component to ensure you're not enabling interception and registering it as an internal/private interface type.

Code to reproduce the issue as a console app:

namespace InterceptorRepro
{
    public interface ICommand<TResult>
    {
    }

    public class StringCommand : ICommand<String>
    {
    }

    public interface ICommandHandler<TCommand, TResult>
        where TCommand : ICommand<TResult>
    {
        TResult Execute(ICommand<TResult> command);
    }

    public class StringCommandHandler : ICommandHandler<StringCommand, String>
    {
        public string Execute(ICommand<string> command)
        {
            return "generic-method";
        }
    }

    public class LoggingInterceptor : IInterceptor
    {
        TextWriter _output;

        public LoggingInterceptor(TextWriter output)
        {
            _output = output;
        }

        public void Intercept(IInvocation invocation)
        {
            _output.Write("Calling method {0} from LoggingInterceptor", invocation.Method.Name);
            invocation.Proceed();
            _output.WriteLine("LoggingInterceptor complete.");
        }
    }

    public class Program
    {
        public static void Main()
        {
            var builder = new ContainerBuilder();
            builder.Register(c => Console.Out).As<TextWriter>();
            builder.RegisterType<LoggingInterceptor>();
            builder
                .RegisterAssemblyTypes(typeof(Program).Assembly)
                .AsClosedTypesOf(typeof(ICommandHandler<,>))
                .EnableInterfaceInterceptors()
                .InterceptedBy(typeof(LoggingInterceptor));

            var container = builder.Build();

            try
            {
                using (var scope = container.BeginLifetimeScope())
                {
                    // Exception thrown on this resolve:
                    var handler = scope.Resolve<ICommandHandler<StringCommand, string>>();
                    Console.WriteLine("Handler type is: {0}", handler.GetType());
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
    }
}

If you remove the EnableInterfaceInterceptors() and InterceptedBy() calls from the registration then the resolution proceeds as expected.

Support for .NET 4.5 in Nuget

It looks like there isn't a build for .NET 4.5 published to Nuget (only 4.5.1).

Nuget error message:

install-package : Could not install package 'Autofac.Extras.DynamicProxy 4.0.0'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.5', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

The EnableClassInterceptors method is not supported.

Test environment: in Autofac. Extras. DynamicProxy. Test. AttributedInterfaceInterceptionFixture, Test to fail.
A:
[Fact]
public void FindsInterceptionAttributeOnReflectionComponentWithClass()
{
var builder = new ContainerBuilder();
builder.RegisterType<C>().EnableClassInterceptors().InterceptedBy(typeof(AddOneInterceptor));
builder.RegisterType<AddOneInterceptor>();
var cpt = builder.Build().Resolve<C>();
Assert.Equal(11, cpt.GetI());
}
B:
[Fact]
public void FindsInterceptionAttributeOnReflectionComponentWithClass2()
{
var builder = new ContainerBuilder();
builder.RegisterType<C2>().EnableClassInterceptors();
builder.RegisterType<AddOneInterceptor>();
var cpt = builder.Build().Resolve<C2>();
Assert.Equal(11, cpt.GetI());
}
[Intercept(typeof(AddOneInterceptor))]
public class C2 : IHasI
{
public C2()
{
I = 10;
}

public int I { get; private set; }

public int GetI()
{
	return I;
}

}

Allow InterceptAttribute to be a non sealed class

I would like to have something like this:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class AuditAttribute : InterceptAttribute
{
public AuditAttribute()
:base(typeof(AuditInterceptor))
{
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class LogAttribute : InterceptAttribute
{
public LogAttribute()
:base(typeof(LogInterceptor))
{
}
}

And using it like this :

[Audit]
[Log]
public class MyClass

It's much better and simpler than having this:

[Intercept(typeof(AuditInterceptor))]
[Intercept(typeof(LogInterceptor))]
public class MyClass

But for me to do that I need the class InterceptAttribute to be a non sealed class.
The non sealed class would have big advantages compared to the sealed class.

  • Much easy to understand and much easy to maintain. I would be using my own code.
  • Just think that if I want to change the class AuditInterceptor to AuditAndEventLogInterceptor, I would have to change it in one place, while using InterceptAttribute I would need to find and replace on every class that I'm using InterceptAttribute and on every module. As you might imagine this might not be practical.

Thanks

Constructor on type 'xxxProxy' not found

When I use Autofac.Extras.DynamicProxy in my wpf project,some aop can't not work with Constructor on type 'xxxProxy' not found.
image
it appears on the wpf progrem has startup.if i resolve the service when I just build the autofaccontainer,it can also works right.so it does very curious。

image

fix castle.core warn

warn info:

Castle.Core 4.0.0 依赖于 System.ComponentModel.TypeConverter (>= 4.0.1),但找不到 System.ComponentModel.TypeConverter 4.0.1。 已解决 System.ComponentModel.TypeConverter 4.1.0 的近似最佳匹配

Update Castle.Core nuspec references

Dependency on Castle.Core 3.2.2 is too strict, suggest at least a sensible interval notation, say through [3.2.2,4.0.0); Castle.Core is released at 3.3.3 now. I don't know how that potentially breaks this.

Calls to other methods within the same class are not being intercepted

Describe the Bug

I've upgraded to the latest Autofac and the main project from .net 4.7.2 to .net core 6, and I''ve noticed a change in behaviour. With the old version, it used to intercept all methods to a class. e.g. If a method called another method within that class, both would be intercepted.

Is this a change in intended change of behaviour, or is this a bug?

Steps to Reproduce

Create asp.net core 6 MVC project.

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());

builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
{
    builder.Register(c => new TestInterceptor());

    builder.RegisterType<Calculator>()
    .As<ICalculator>()
    .EnableInterfaceInterceptors()
    .InterceptedBy(typeof(TestInterceptor));
});

Then the Test Interceptor

    public class TestInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            invocation.Proceed();
        }
    }

And finally the Controller method

        public HomeController(ICalculator calc)
        {
            _calc = calc;
            var a =_calc.Add(1, 2); // intercepted
            var b = _calc.Subtract(4, 2);   // intercepted
            var c = _calc.SomeMaths(10, 11); // intercepted, but not when SomeMaths() calls Add and Subtract

        }

Expected Behavior

For Add() and Subtract() to be intercepted when called from SomeMethod()

Exception with Stack Trace

n/a

Dependency Versions

<PackageReference Include="Autofac" Version="6.5.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Autofac.Extras.DynamicProxy" Version="6.0.1" />

Additional Info

n/a

Castle.Core version 4.0.0 causes NuGet dependency warnings

The castle.Core version used in Autofac.Extras.DynamicProxy is casing dependency warnings.

warning NU1603: Castle.Core 4.0.0 depends on System.ComponentModel.TypeConverter (>= 4.0.1) but System.ComponentModel.TypeConverter 4.0.1 was not found. An approximate best match of System.ComponentModel.TypeConverter 4.1.0 was resolved.

<PackageReference Include="Castle.Core" Version="4.0.0" />

It has been fixed in Castle.Core 4.1.0. Please consider updating to a newer version.

The execution time of the EnableClassInterceptors method is gradually increasing.

TargetFramework: netcoreapp3.1

Autofac.Extensions.DependencyInjection version 6.0.0
Autofac.Extras.DynamicProxy version 5.0.0

The steps to reproduce the problem are:

The source code of the project that can reproduce the problem: https://github.com/maliming/ClassInterceptorTest

Create a simple mvc project and add a lot of controllers.

Controller.cs

public abstract class MyControllerBase : Controller
{
}

[Route("api/testapi/test0api")]
public class Test0ControllerBase : MyControllerBase
{
	[HttpGet]
	[Route("Get")]
	public string TestMethod()
	{
		return "test";
	}
}

[Route("api/testapi/test1api")]
public class Test1ControllerBase : MyControllerBase
{
	[HttpGet]
	[Route("Get")]
	public string TestMethod()
	{
		return "test";
	}
}

//Test100ControllerBase 

Program.cs

public class Program
{
	public static void Main(string[] args)
	{
		var host = Host.CreateDefaultBuilder(args)
			.UseServiceProviderFactory(new AutofacServiceProviderFactory())
			.ConfigureWebHostDefaults(webHostBuilder =>
			{
				webHostBuilder.UseStartup<Startup>();
			})
			.Build();

		host.Run();
	}
}

Startup.cs

public class Startup
{
	public void ConfigureServices(IServiceCollection services)
	{
		services.AddControllers();
	}

	public void ConfigureContainer(ContainerBuilder builder)
	{
		foreach (var type in Assembly.GetExecutingAssembly().GetTypes()
		.Where(x => typeof(MyControllerBase).IsAssignableFrom(x)))
		{
			var stopwatch = Stopwatch.StartNew();

			builder.RegisterType(type)
				.As(type)
				.EnableClassInterceptors();

			stopwatch.Stop();
			Console.WriteLine(type.Name + " => ElapsedMilliseconds:" + stopwatch.ElapsedMilliseconds);
		}
	}
	
	public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
	{
		if (env.IsDevelopment())
		{
			app.UseDeveloperExceptionPage();
		}

		app.UseHttpsRedirection();

		app.UseRouting();

		app.UseAuthorization();

		app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
	}
}

My code enables class interception for each controller.

builder.RegisterType(type)
		.As(type)
		.EnableClassInterceptors();

Ideally, the execution time of the EnableClassInterceptors method should be about the same.

But the result is that time is gradually increasing.

Console output:

MyControllerBase => ElapsedMilliseconds:147
Test0ControllerBase => ElapsedMilliseconds:73
Test1ControllerBase => ElapsedMilliseconds:83
Test2ControllerBase => ElapsedMilliseconds:130
Test3ControllerBase => ElapsedMilliseconds:156
Test4ControllerBase => ElapsedMilliseconds:174
Test5ControllerBase => ElapsedMilliseconds:197
Test6ControllerBase => ElapsedMilliseconds:224
Test7ControllerBase => ElapsedMilliseconds:243
Test8ControllerBase => ElapsedMilliseconds:286
Test9ControllerBase => ElapsedMilliseconds:293
Test10ControllerBase => ElapsedMilliseconds:319
Test11ControllerBase => ElapsedMilliseconds:341
Test12ControllerBase => ElapsedMilliseconds:374
Test13ControllerBase => ElapsedMilliseconds:399
Test14ControllerBase => ElapsedMilliseconds:415
Test15ControllerBase => ElapsedMilliseconds:447
Test16ControllerBase => ElapsedMilliseconds:484
Test17ControllerBase => ElapsedMilliseconds:496
Test18ControllerBase => ElapsedMilliseconds:524
Test19ControllerBase => ElapsedMilliseconds:552
Test20ControllerBase => ElapsedMilliseconds:570
Test21ControllerBase => ElapsedMilliseconds:642
Test22ControllerBase => ElapsedMilliseconds:635
Test23ControllerBase => ElapsedMilliseconds:658
Test24ControllerBase => ElapsedMilliseconds:677
Test26ControllerBase => ElapsedMilliseconds:787
Test27ControllerBase => ElapsedMilliseconds:792
Test28ControllerBase => ElapsedMilliseconds:811
Test29ControllerBase => ElapsedMilliseconds:831
Test30ControllerBase => ElapsedMilliseconds:848
Test31ControllerBase => ElapsedMilliseconds:912
Test32ControllerBase => ElapsedMilliseconds:917
Test33ControllerBase => ElapsedMilliseconds:945
Test34ControllerBase => ElapsedMilliseconds:973
Test35ControllerBase => ElapsedMilliseconds:1028
Test36ControllerBase => ElapsedMilliseconds:1024
Test37ControllerBase => ElapsedMilliseconds:1056
Test38ControllerBase => ElapsedMilliseconds:1082
Test39ControllerBase => ElapsedMilliseconds:1107
Test40ControllerBase => ElapsedMilliseconds:1132
Test41ControllerBase => ElapsedMilliseconds:1195
Test42ControllerBase => ElapsedMilliseconds:1215
Test43ControllerBase => ElapsedMilliseconds:1236

Should document Visual Studio and C# language dependencies

You should probably document the C# language dependencies, i.e. nameof operator, for starters; implied also Visual Studio along with that. Background, I've been happily tooling along on VS2013. While I did spend a little time getting acquainted with VS2015 around about the CTP, I haven't made the leap yet, much less C# 6.0. I probably should, but just haven't made it a priority yet.

Delay creation of class interceptor proxies until activating

Hi Guys

I've noticed that all ClassInterceptor Proxies getting created while Registration. In my case this is a Performance Issue because i'm intercepting every of my ViewModels. Now i have a noticable delay on the start up. I've seen that the InterfaceInterceptors are getting created in a Activating Handler.
Is there a way to create the class proxies also in a Activating Handler or is there another way to improve the performance?

Intercept controllers methods ASP 5

I'm using ASP NET 5 in rc1-final version.
My autofac-related dependencies are:

"Autofac.Extensions.DependencyInjection": "4.0.0-rc1-177",
"Autofac.Extras.DynamicProxy": "4.0.0-beta8-231",

Is there a possibility to intercept controller's methods?
I've tried with some 'normal' classes and everything worked fine. Problem occurs when I try to do stuff with MVC controllers. Tried already:

  • implementing custom interface (interface intercepting):
    public interface IMyInterface
    {
        IActionResult Get(int id);
    }

    [Intercept("log-calls")]
    public class MyController : Controller, IMyInterface
    {
        public IActionResult Get(int id)
        {
            return new JsonResult(new SomeClass(id));
        }
    }

    public class CallLogger : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            //breakpoint here
            invocation.Proceed();
        }
    }

And part of ConfigureServices:

    ...
    services.AddMvc();
    ...
    builder.RegisterType<MyController>()
        .As<IMyInterface>()
        .EnableInterfaceInterceptors();

    builder.Register(c => new CallLogger())
        .Named<IInterceptor>("log-calls");

    builder.Populate(services);

    var container = builder.Build();

    return container.Resolve<IServiceProvider>();
  • registering controller as class (class intercepting) - similar to above just without interface, EnableInterfaceInterceptors -> EnableClassInterceptors and virtual method Get(int) method in controller.

But nothing worked. Am I missing something or is it not possible to do that now?

PropertyChanged behavior broken if interface interception used in WPF app

Describe the Bug

I'm trying to intercept viewmodels' interfaces by interface interceptors. Defined a simple logging interceptor, registered at type registration and opened new windows which's DataContext is binded to the before mentioned viewmodel. The viewmodel is resolved via viewmodel locator, which gets the viewmodel from the built container. If I define .EnableInterfaceInterceptors() at viewmodel registration, it's propertychanged behavior gets broken, the view is not aware of the binded property's changes. Without .EnableInterfaceInterceptors() the binding is working fine.

Steps to Reproduce

Register a viewmodel as an interface's implementation and enable interface interception on it. Created a test app as you can see below:

MainWindow, which registers the viewmodel and builds-, sets the container

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var builder = new ContainerBuilder();

        builder.Register(c => new LoggingInterceptor());

        builder.RegisterType<BindedViewModel>().SingleInstance().As<IBindedViewModel>()
            .InstancePerLifetimeScope()
            .PropertiesAutowired();
            //.EnableInterfaceInterceptors();

        AfContainer.Container = builder.Build();
        ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(AfContainer.Container));
    }

    private void Button_Click_3(object sender, RoutedEventArgs e)
    {
        var win = new BindedWindow();
        win.Show();
    }
}

Window which has binded property

<Window x:Class="AutofacTester.BindedWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="BindedWindow" Height="250" Width="300"
        DataContext="{Binding Source={StaticResource Locator}, Path=BindedVM}">

    <Grid>
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5" Text="{Binding StatusText, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
                   FontSize="14"/>
    </Grid>
</Window>

Viewmodel's interface

namespace AutofacTester.Interfaces
{
    [Intercept(typeof(LoggingInterceptor))]
    public interface IBindedViewModel : INotifyPropertyChanged
    {
        string StatusText { get; }
    }
}

Viewodel

namespace AutofacTester.Implementations
{
    public sealed class BindedViewModel : IBindedViewModel
    {
        private readonly Timer _counterTimer;
        private int _counter;
        private string _statusText;

        public event PropertyChangedEventHandler? PropertyChanged;

        public string StatusText
        {
            get => _statusText;
            private set
            {
                _statusText = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(StatusText)));
            }
        }

        public BindedViewModel()
        {
            StatusText = "Test";
            _counterTimer = new Timer(_ => SetStatusText(), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
        }

        private void SetStatusText()
        {
            _counter++;
            StatusText = $"Current counter: {_counter}";
            System.Diagnostics.Debug.WriteLine(">>> StatusText set to: " + StatusText);
        }
    }
}

Interceptor

public class LoggingInterceptor : IInterceptor
{
    void IInterceptor.Intercept(IInvocation invocation)
    {
        System.Diagnostics.Debug.WriteLine($">>>> Calling method {invocation.Method.Name} with parameters ({string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())})");
        invocation.Proceed();
        System.Diagnostics.Debug.WriteLine($">>>> Done: result was {invocation.ReturnValue}.");
        System.Diagnostics.Debug.WriteLine($">>>> Module: {invocation.TargetType.Module.Name}");
    }
}

ViewModel locator

public sealed class ViewModelLocator
{
    public IBindedViewModel BindedVM => ServiceLocator.Current.GetInstance<IBindedViewModel>();
}

A static class to hold the Container with the registered types

public static class AfContainer
{
    public static IContainer Container { get; set; }
}

Expected Behavior

Binding should work with .EnableInterfaceInterceptors() too.

Dependency Versions

TFM net6.0-windows
WPF (UseWPF set to true in csproj)

Autofac: 7.0.0, tested with earlier versions as well
Autofac.Extras.CommonServiceLocator: 6.0.1
Autofac.Extras.DynamicProxy: 6.0.1

Attempting to resolve intercepted types using class interceptors does not throw exception when a dependency is unmet

I have a set of tests in place to ensure that all of my composition roots are able to be resolved. This has been working fine. I recently added a couple interceptors for logging and exception handling on my composition roots.

It would seem that even if a dependency is unmet, AutoFac will resolve the DynamicProxy and set null for any unmet dependencies, without throwing the standard Autofac.Core.Registration.ComponentNotRegisteredException. This causes the test to erroneously pass.

I commented out the interceptor registration, and the tests fail as expected.

Autofac Not Intercepting

From @CShelton11 on June 5, 2018 21:25

I cannot get autofac to intercept. I have the following setup in my .net core application:

// ************************************************
// Logger created:
// ************************************************

public class Logger : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // Logging removed for now
        var watch = System.Diagnostics.Stopwatch.StartNew();  // Added break point here
        invocation.Proceed(); 
        watch.Stop();
        var executionTime = watch.ElapsedMilliseconds;
    }
}

// ************************************************
// Class Created:
// ************************************************

[Intercept(typeof(Logger))]
public class ServiceProxy: ServiceInterface
{
    public User GetUser(String username, String password)
    {
        var service = ServiceHelper.GetODataClaimService();
        var query = from a in service.Users
                            select a;
        var dsq = query.ToDataServiceQuery<User>();
        var result = dsq.ToListSync<User>();
        var user = result.FirstOrDefault();
        return user;
    }
}

// ************************************************
// Interface Created:
// ************************************************

public interface ServiceInterface
{
    User GetUser(String username, String password);
}

// ************************************************
// Interception Configuration
// ************************************************

public class Interceptor
{
    public static void Configure()
    {
        var builder = new ContainerBuilder();
        builder.Register(a => new Logger());
        builder.RegisterType<ServiceProxy>().As<ServiceInterface>().EnableInterfaceInterceptors().InterceptedBy(typeof(Logger));  // Tried removing intercepted by
        var container = builder.Build();
        var worker = container.Resolve<ServiceInterface>();
        builder.Build()
    }
}

I put a break point in the logger to see if it ever enters that block of code.
It never does. What am I missing here?
I've tried quite a few configurations but nothing seems to work.
Also - The Configure method is invoked from application Startup..

Please advise.

Copied from original issue: autofac/Documentation#56

Provided example with typed interceptor is not working

Hi,

I tried to intercept an interface and parts of the the example provided here (create-interceptors)

I tried this yesterday and was confused as it seems widely used, documented but not working in my code. I already doubt my code until I tried to use the provided code in the example to make an test.
I even tried to clone this repository to find an appropriate test, which would had helped me, to find out how to do it, but I could not build the solution directly from visual studio 2017. As I did recently installed my PC, it lacks some build tools.

So I made an test project.
EnableInterfaceInterceptor.zip

It includes the packages.config and the code but which is not more than following.

  • Assembly version information for all project dependencies (packages.config, project.json)
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Autofac" version="4.6.2" targetFramework="net461" />
  <package id="Autofac.Extras.DynamicProxy" version="4.2.1" targetFramework="net461" />
  <package id="Castle.Core" version="4.0.0" targetFramework="net461" />
  <package id="NUnit" version="3.9.0" targetFramework="net461" />
  <package id="NUnit3TestAdapter" version="3.9.0" targetFramework="net461" />
</packages>
  • If possible, a reproduction of the issue (ideally in a unit test form).
    [TestFixture]
    class InterfaceInterceptorLogging
    {
        [Test]
        public void ShouldWork()
        {
            var autoResetEvent = new AutoResetEvent(false);

            var builder = new ContainerBuilder();
            builder.RegisterType<SomeType>()
                .As<ISomeInterface>()
                .EnableInterfaceInterceptors();

            builder.Register(c => new CallLogger(Console.Out, autoResetEvent));
            using (var container = builder.Build())
            {
                var willBeIntercepted = container.Resolve<ISomeInterface>();

                willBeIntercepted.TryStart();

                Assert.IsTrue(autoResetEvent.WaitOne(TimeSpan.FromMilliseconds(5)));
            }
        }

    }

    public interface ISomeInterface
    {
        void TryStart();
    }

    public class SomeType : ISomeInterface

    {
        public void TryStart()
        {
            Console.WriteLine("TryStart");
        }
    }

    public class CallLogger : IInterceptor
    {
        readonly TextWriter _output;
        readonly AutoResetEvent _autoResetEvent;

        public CallLogger(TextWriter output, AutoResetEvent autoResetEvent)
        {
            _autoResetEvent = autoResetEvent;
            _output = output;
        }

        public void Intercept(IInvocation invocation)
        {
            Assert.IsTrue(_autoResetEvent.Set());

            _output.Write("Calling method {0} with parameters {1}... ",
                invocation.Method.Name,
                string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()));

            invocation.Proceed();

            _output.WriteLine("Done: result was {0}.", invocation.ReturnValue);
        }
    }

Autofac.Extensions.DependencyInjection 6.0 version cannot be used aop

hello,
If it's 5.0, there's no problem,
But if I upgrade to Autofac.Extensions.DependencyInjection 6.0,

<ItemGroup>
PackageReference Include" "Autofac.Extensions.DependencyInjection""Version" "6.0.0" /
PackageReference Include" "Autofac.Extras.DynamicsProxy" Version" "4.5.0" /
</ItemGroup>

will be reported error:

An unhandled antalysed dysd while processing the request.
ProxyGenerationException: This is a DynamicSProxy2 error: Target type for the proxy implements Castle.Dynamics.IProxyAccessorTarget is a Dynamics infrastructure interface and you want never it. Are Are you trying to proxy an exist proxying?

There's a question here:
Unable to hook up interceptor on classes/interfaces in asp.net core 3.1 application

How to register target instance with interceptors

Hello,

Okay, so I register my IInterceptor with the container builder. However, InterceptedBy does not want provide any sort of context, nor does it seem to want any types in terms of IInterceptor.

Further, InterceptedBy seems to want Services, Types, or names; not sure how that aligns to my IInterceptor. Or perhaps I've got the wrong extension method in mind here...

Thanks...

PropertiesAutowired not working when EnableInterfaceInterceptors and AllowCircularDependencies

I use Autofac DynamicProxy2 do AOP logging. If I register like this:

builder.RegisterAssemblyTypes(assemblys.ToArray()).Where(t => t.Name.EndsWith("ServiceImpl"))
                .AsImplementedInterfaces()
                .InstancePerLifetimeScope()
                .PropertiesAutowired()
                .EnableInterfaceInterceptors()
                .InterceptedBy(typeof(LogInterceptor));
            ;

then ValuesServiceImpl instance can be auto wire to property, like this:

public class ValuesController : ApiController
    {
        public IValuesService ValuesService { get; set; }
    }

But if I use PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)

builder.RegisterAssemblyTypes(assemblys.ToArray()).Where(t => t.Name.EndsWith("ServiceImpl"))
                    .AsImplementedInterfaces()
                    .InstancePerLifetimeScope()
                    .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
                    .EnableInterfaceInterceptors()
                    .InterceptedBy(typeof(LogInterceptor));

then PropertiesAutowired not working, ValuesService property is null.

In my project I must allow Circular Dependencies, and I prefer use EnableInterfaceInterceptors instead of EnableClassInterceptors

Allowing interceptor parameters to be specified.

Currently it's not possible to specify parameters to be used when resolving an interceptor service.
I recently had a need for this and I thought that it might be useful for others as well.

One scenario would be to supply configuration options to the interceptor.

Usage would be as follows:

builder.RegisterType<Service>()
    .As<IService>()  
    .EnableInterfaceInterceptors()  
    .InterceptedBy(typeof(CachingInterceptor), TypedParameter.From(new InMemoryCache()), [...]);

or with attributes

[Intercept(typeof(LoggingInterceptor), LogLevel.Debug, [...])]
class Service : IService {}

I have a PR ready that we can discuss if this is of interest.

Conditional registration for interceptors

Problem Statement

Based on autofac/Autofac#1211 - it may be interesting to have the ability to conditionally enable interception based on a lambda expression. This does somewhat overlap with #29.

Desired Solution

I imagine the usage would be like:

builder
  .RegisterAssemblyTypes(typeof(Program).Assembly)
  .AsClosedTypesOf(typeof(ICommandHandler<,>))
  .EnableInterfaceInterceptors(t => t.HasSpecificAttributeICareAbout())
  .InterceptedBy(typeof(LoggingInterceptor));

That is, you could act on the registration based on the type being registered. (Honestly, this part needs some work. I haven't thought it all the way through. It may be there's a better way to go here.)

AutoFac 5.0 not supported

Now that Aufofac 5.0 has been released, the integration with Autofac.Extras.DynamicProxy throws an exception.

Here is a test repo demonstrating the error.

It looks to be because of this commit and that ComponentRegistration.RaiseActivating is now being called twice. This causes an error when calling the second ProxyGenerator.CreateInterfaceProxyWithTarget:

Castle.DynamicProxy.ProxyGenerationException: This is a DynamicProxy2 error: Target type for the proxy implements Castle.DynamicProxy.IProxyTargetAccessor which is a DynamicProxy infrastructure interface and you should never implement it yourself. Are you trying to proxy an existing proxy?

The usage of interceptors in unit tests and executing them with the console force the load of autofac version 4.0.0.0

Hi guys,

I just ran into a possible issue with this nuget package (Version 4.2.1.0).
When i use the interceptors in a unit test like

builder.Register(c=> new List<object>()).EnableInterfaceInterceptors();

the test fails when i start it with the nunit console with the error:
System.IO.FileLoadException : Could not load file or assembly 'Autofac, Version=4.0.0.0, Cu lture=neutral, PublicKeyToken=17863af14b0044da' or one of its dependencies. The located ass embly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

Which make sense, since im having the later version of autofac in use 4.1.1.0.

Is it possible that this package depends uppon a specific version of autofac?
If so the documentation should be adjusted. But i guess that this could be a bug.

BR Nick

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.