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