3

In our real world application we defined an attribute that is used to enable logging in methods or classes (the usual AOP use case). When we apply this attribute to a WPF window class, objects of this class can't be created by Ninject. Here is a minimal example to reproduce the issue:

dummy interceptor for logging:

public class MyInterceptor: IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("Calling {0} at {1}", invocation.Request.Method.Name, DateTime.Now);
        invocation.Proceed();
    }
}

the corresponding attribute:

public class MyAttribute: InterceptAttribute
{
    public override IInterceptor CreateInterceptor(IProxyRequest request)
    {
        return new MyInterceptor();
    }
}

the window class (completely empty, only the automatically generated empty grid is inside):

[My]
public partial class MainWindow: Window 
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

and finally the app startup code where the object is requested:

public partial class App: Application
{
    private void Application_Startup(object sender, StartupEventArgs e)
    {
        var kernel = new StandardKernel(new NinjectSettings() { LoadExtensions = false }, new DynamicProxyModule());
        var window = kernel.Get<MainWindow>();
        window.ShowDialog();
    }
}

When requesting the window via kernel.Get<MainWindow>(); an TargetInvocationException is thrown with an inner exception telling me that Castle.Proxies.MainWindowProxy doesn't have a resource specified by URI "/NinjectInterceptionWPF;component/mainwindow.xaml" where NinjectInterceptionWPF is our assembly's short name.

When we look at the automatically created InitializeComponent of MainWindow we can see that an URI is created to address the XAML code, which seems to be missing for the proxy:

System.Uri resourceLocater = new System.Uri("/NinjectInterceptionWPF;component/mainwindow.xaml", System.UriKind.Relative);
#line 1 "..\..\..\MainWindow.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);

I already played around a bit and tried to use an absolute URI but LoadComponent only accepts relative ones.

Some internet searching shows that a lot of people use Ninject Interception and DynmaicProxy for WPF binding (INotifyPropertyChanged), so I think in general it should be possible to build a proxy of a WPF window.

But how?

Silas
  • 1,140
  • 11
  • 12

1 Answers1

2

The interception extension of Ninject created a new dynamic assembly. This means you won't be able to load resources with a relative path. But the question here is if you really want to create a dynamic proxy for the view. Usually you should do this on your ViewModel instead.

Remo Gloor
  • 32,665
  • 4
  • 68
  • 98
  • Ok, so it's not possible, isn't it? The WPF app does _not_ follow the MVVM pattern since it's more or less a GUI wrapper to visualize the API of a library and doesn't has any data that could be used for binding (if you ingore things like return values of library calls and so on). – Silas Jul 02 '12 at 12:47
  • Hy If you follow the MVVM pattern the view should not need to implement INotifyPropertyChanged. This is a concern of the view model! Even if your applications is only showing an API I guess you need to invoke stuff on your demonstrated API which should be done in a command (which is owned by the ViewModel) – Daniel Marbach Jul 03 '12 at 04:46