AOP с перехватом Ninject, Castle DynamicProxy и окном WPF: не удается найти ресурс XAML в DynamicProxy окна

В нашем реальном приложении мы определили атрибут, который используется для включения регистрации в методах или классах (обычный вариант использования АОП). Когда мы применяем этот атрибут к классу окна WPF, объекты этого класса не могут быть созданы Ninject. Вот минимальный пример для воспроизведения проблемы:

фиктивный перехватчик для ведения журнала:

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

соответствующий атрибут:

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

класс окна (полностью пустой, внутри находится только автоматически сгенерированная пустая сетка):

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

и, наконец, код запуска приложения, в котором запрашивается объект:

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();
    }
}

При запросе окна через kernel.Get<MainWindow>(); выдается TargetInvocationException с внутренним исключением, сообщающим мне, что Castle.Proxies.MainWindowProxy не имеет ресурса, указанного URI "/NinjectInterceptionWPF;component/mainwindow.xaml", где NinjectInterceptionWPF — это короткое имя нашей сборки.

Когда мы смотрим на автоматически созданные InitializeComponent из MainWindow, мы видим, что URI создается для обращения к коду XAML, который, похоже, отсутствует для прокси:

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

Я уже немного поигрался и попытался использовать абсолютный URI, но LoadComponent принимает только относительные.

Некоторый поиск в Интернете показывает, что многие люди используют Ninject Interception и DynmaicProxy для привязки WPF (INotifyPropertyChanged), поэтому я думаю, что в целом должно быть возможно создать прокси окна WPF.

Но как?


person Silas    schedule 27.06.2012    source источник


Ответы (1)


Расширение перехвата Ninject создало новую динамическую сборку. Это означает, что вы не сможете загружать ресурсы с относительным путем. Но вопрос здесь в том, действительно ли вы хотите создать динамический прокси для представления. Обычно вы должны делать это на своей ViewModel.

person Remo Gloor    schedule 02.07.2012
comment
Хорошо, так что это невозможно, не так ли? Приложение WPF не следует шаблону MVVM, так как это более или менее оболочка с графическим интерфейсом для визуализации API библиотеки и не имеет никаких данных, которые можно было бы использовать для привязки (если вы читаете такие вещи, как возвращаемые значения библиотечных вызовов и так далее). - person Silas; 02.07.2012
comment
Hy Если вы следуете шаблону MVVM, представлению не нужно реализовывать INotifyPropertyChanged. Это забота модели представления! Даже если ваши приложения отображают только API, я думаю, вам нужно вызывать что-то в продемонстрированном вами API, что должно быть выполнено в команде (которая принадлежит ViewModel) - person Daniel Marbach; 03.07.2012