为拦截类型添加 ViewModel 到 View 类型映射

Add ViewModel to View type mapping for intercepted types

我在 WPF 应用程序中同时使用 Caliburn Micro 和 Ninject。我正在使用 Ninject.Extensions.Interception 来拦截和记录对我的 ViewModels 的调用,但是这会阻止 Caliburn 定位 ViewModels 的视图,因为 Caliburn 被传递给拦截的 viewModel(代理),它具有不同的命名空间和名称。

例如,而不是得到:

MyApp.ViewModels.OrdersViewModel

正在获取:

Castle.Proxies.IOrdersProxy

更复杂的是,ViewModel 和 View 位于不同的程序集中,因此无法假定命名空间。

因为我需要在运行时询问代理,所以我需要一种方法来以编程方式连接到视图分辨率,而不是通过添加字符串映射。我看不出有什么方法可以做到这一点 - Calliburn Micro 有可能吗?

好的,我知道了。我没有打映射,而是在 WindowManager 中解包代理:

using System;
using System.Collections.Generic;
using Caliburn.Micro;
using Castle.DynamicProxy;

namespace CAM.Utility
{
    public class WindowManagerEx : WindowManager, IWindowManagerEx
    {
        private readonly List<object> _trayIcons;

        public WindowManagerEx()
        {
            _trayIcons = new List<object>();
        }

        public override bool? ShowDialog(object rootModel, object context = null, IDictionary<string, object> settings = null)
        {
            rootModel = rootModel.UnwrapProxy();

            return base.ShowDialog(rootModel, context, settings);
        }

        public override void ShowWindow(object rootModel, object context = null, IDictionary<string, object> settings = null)
        {
            rootModel = rootModel.UnwrapProxy();

            base.ShowWindow(rootModel, context, settings);
        }

        public override void ShowPopup(object rootModel, object context = null, IDictionary<string, object> settings = null)
        {
            rootModel = rootModel.UnwrapProxy();

            base.ShowPopup(rootModel, context, settings);
        }

        public bool? ShowDialog<TViewModel>(object context = null, IDictionary<string, object> settings = null)
        {
            var viewModelInstance = IoC.Get<TViewModel>();

            return ShowDialog(viewModelInstance, context, settings);
        }

        public void ShowWindow<TViewModel>(object context = null, IDictionary<string, object> settings = null)
        {
            var viewModelInstance = IoC.Get<TViewModel>();

            ShowWindow(viewModelInstance, context, settings);
        }

        public void ShowPopup<TViewModel>(object context = null, IDictionary<string, object> settings = null)
        {
            var viewModelInstance = IoC.Get<TViewModel>();

            ShowPopup(viewModelInstance, context, settings);
        }

        public void ShowTrayIcon<TViewModel>(object context = null)
        {
            var viewModelInstance = IoC.Get<TViewModel>();

            _trayIcons.Add(viewModelInstance);
        }

        public void Dispose()
        {
            foreach (var trayIcon in _trayIcons)
            {
                var disposable = trayIcon as IDisposable;
                if (disposable != null)
                {
                    disposable.Dispose();
                }
            }
        }
    }

    public static class CastleProxyExtensions
    {
        public static object UnwrapProxy(this object target)
        {
            var proxy = target as IProxyTargetAccessor;

            if (proxy != null)
            {
                dynamic dynamicProxy = proxy;

                dynamic interceptors = dynamicProxy.__interceptors;

                dynamic interceptor = interceptors[0];

                target = interceptor.Instance;
            }

            return target;
        }
    }
}

如果您想知道 IWindowManagerEx 是什么:

public interface IWindowManagerEx : IWindowManager, IDisposable
{
    bool? ShowDialog<TViewModel>(object context = null, IDictionary<string, object> settings = null);

    void ShowWindow<TViewModel>(object context = null, IDictionary<string, object> settings = null);

    void ShowPopup<TViewModel>(object context = null, IDictionary<string, object> settings = null);

    void ShowTrayIcon<TViewModel>(object context = null);
}