Caliburn视图模型上的城堡温莎拦截器

时间:2012-02-12 19:33:32

标签: castle-windsor aop caliburn interceptor

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

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

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

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

这是一个简单的View Model类 - 它是“tab item”:

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框架通过命名约定匹配View和View Model。

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

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

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

那么正确的方法是什么?

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

这个怎么样?

void Hack()
{
    var existing = ViewLocator.TransformName;
    ViewLocator.TransformName = (s, o) =>
                                existing(s.EndsWith("Proxy")
                                            ? s.Substring(0, s.Length - "Proxy".Length)
                                            : s, o);
}

答案 1 :(得分: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);
    };
}