0

我想用 Castle Windsor Interceptor 创建自己的方面并应用于 View Model 类。

正如我所说,我使用 Caliburn MVVM 框架,在 DI 上我使用 Caste Windsor。一切正常。

例如我创建了简单的日志拦截器,这里是:

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.Write("Log: Method Called: " + invocation.Method.Name);
        invocation.Proceed();
    }
}

这是简单的 View Model 类 - 它是“选项卡项”:

public class TabViewModel : Screen, 
    ITabViewModel
{

}

当我使用 Fluent API 配置 IoC 时,我想在 View Model 类上应用这个拦截器。

       container.Register(Component
                    .For<LoggingInterceptor>()
                    .LifeStyle
                        .Singleton
                    .Named("LogAspect"));

        container.Register(Component
                    .For<ITabViewModel>()
                    .ImplementedBy<TabViewModel>()
                    .LifeStyle
                        .Transient
                    .Named("TabViewModel")
                    .Interceptors<LoggingInterceptor>());

当我尝试从 IoC 选择视图模型时:

var tabItem = IoC.Get<ITabViewModel>();
ActivateItem(tabItem);

我收到了这条消息:

未找到 Castle.Proxies.ITabViewModelProxy 的默认视图。搜索的视图包括:Castle.Proxies.IITabViewModelProxy Castle.Proxies.ITabViewModelProxys.IDefault Castle.Proxies.ITabViewModelProxys.Default

我也尝试过这种方式用于拦截器应用程序。

[Interceptor(typeof(LoggingInterceptor))]
public class TabViewModel : Screen, 
    ITabViewModel
{

}

好的,我知道 Caliburn 框架通过命名约定匹配视图和视图模型。

当我尝试选择 ITabViewModel 的实现时,我得到了 ITabViewModelProxy,而对于 ITabViewModelProxy,我没有注册任何视图。

代理的目标是 TabViewModel 但我认为问题在于命名不匹配。

我不想重命名 ViewModel,因为我想从 XML 文件配置代理。

那么什么是正确的方法呢?

谢谢你的帮助

4

2 回答 2

1

那这个呢?

void Hack()
{
    var existing = ViewLocator.TransformName;
    ViewLocator.TransformName = (s, o) =>
                                existing(s.EndsWith("Proxy")
                                            ? s.Substring(0, s.Length - "Proxy".Length)
                                            : s, o);
}
于 2012-05-08T21:51:46.480 回答
0

最简单的方法(并且可能是健壮的)是建议 Caliburn 的 ViewLocator 使用的不是视图模型代理的类型,而是被代理的视图模型的类型:

public static void AddViewLocatorRuleForProxiedViewModels()
{
    var originalViewTypeLocator = ViewLocator.LocateTypeForModelType;

    ViewLocator.LocateTypeForModelType = (modelType, displayLocation, context) =>
    {
        var viewModelType = modelType;

        var viewModelTypeName = viewModelType.FullName;
        if (viewModelTypeName.StartsWith("Castle.Proxies") && viewModelTypeName.EndsWith("Proxy"))
            viewModelType = viewModelType.BaseType;

        return originalViewTypeLocator(viewModelType, displayLocation, context);
    };
}
于 2013-03-04T11:19:06.700 回答