为拦截类型添加 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);
}
我在 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);
}