0

私はWPFアプリでCaliburn MicroとNinjectを一緒に使用しています。ViewModels への呼び出しをインターセプトしてログに記録するために使用Ninject.Extensions.Interceptionしていますが、Caliburn が別の名前空間と名前のインターセプトされたビューモデル (プロキシ) を渡されているため、Caliburn が ViewModels のビューを見つけることができません。

たとえば、取得する代わりに:

MyApp.ViewModels.OrdersViewModel

それは得ています:

Castle.Proxies.IOrdersProxy

さらに複雑なことに、ViewModel と View は異なるアセンブリに配置されているため、名前空間を想定できません。

実行時にプロキシに問い合わせる必要があるため、文字列マッピングを追加するのではなく、プログラムでビューの解決にフックする方法が必要です。これを行う方法がわかりません - Calliburn Micro で可能ですか?

4

1 に答える 1

1

はい、分かりました。マッピングと戦う代わりに、代わりに 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);
}
于 2015-01-16T18:32:10.887 に答える