Caliburn with Castles DynamicProxy:找不到视图
Caliburn with Castles DynamicProxy: Cannot find view
对于我正在进行的一个项目,我尝试将 Caliburn 与城堡 dynamicProxy 结合起来。我的目标是拦截视图调用的视图模型对象的所有方法。 Caliburn 按照约定自动将视图模型方法(这是 Caliburn 用于连接例如按钮命令以查看模型方法的原则)到视图的特定元素。因此,我重写了用于实例化 ViewModel 类 的 caliburns GetInstance 方法。在这个方法中,我用动态代理包装每个视图模型,然后 return 它:
protected override object GetInstance(Type serviceType, string key)
{
var instance = container.GetInstance(serviceType, key);
if (instance != null)
{
object ret = pg.CreateClassProxyWithTarget(instance.GetType(), (instance), new LoggingInterceptor());
return ret;
}
throw new Exception("Could not locate any instances.");
//return null;
}
不幸的是,这次更改后我的视图只显示
Cannot find view for Castle.Proxies.FirstViewModelProxy.
因为我知道castles dynamicproxy将字符串"Proxy"添加到新创建的类型的末尾,而caliburn会替换字符串末尾的Model一词,然后尝试使用该字符串找到相应的视图我添加了另一个 NameTransformer 规则:
public CaliburnBootstrapper()
{
LogManager.GetLog = type => new DebugLogger(type);
Initialize();
ViewLocator.NameTransformer.AddRule("ModelProxy$", string.Empty);
}
但这并没有改变任何东西。如何解决这个问题?
经过更多研究后,我发现自己如何做到这一点:Caliburn 允许交换负责视图模型名称转换的方法以查看。所以我所做的就是自己调用原始名称转换方法。当它没有 returns 任何东西时,我会尝试自己的逻辑。成功了。
Func<string, object, IEnumerable<string>> orig = ViewLocator.TransformName;
ViewLocator.TransformName = new Func<string,object,IEnumerable<string>>(
delegate(string a, object b )
{
IEnumerable<string> ret = orig(a,b);
if (ret.Count() > 0)
{
return ret;
}
a = Regex.Replace(a, "^Castle.Proxies", "CaliburnSample.Views");
a = Regex.Replace(a, "ModelProxy$", string.Empty);
a = Regex.Replace(a, "Model$", string.Empty);
return new string[] { a };
}
);
更新:
几乎一切正常。按钮按照惯例绑定到方法等。但不幸的是,属性通知不再起作用了。视图不再使用属性的新内容进行更新,尽管它们受 caliburn 约束:
INFO: [2015-12-09T11:36:30.2646933+01:00] Binding Convention Applied: Element TxtMsg.
对于我正在进行的一个项目,我尝试将 Caliburn 与城堡 dynamicProxy 结合起来。我的目标是拦截视图调用的视图模型对象的所有方法。 Caliburn 按照约定自动将视图模型方法(这是 Caliburn 用于连接例如按钮命令以查看模型方法的原则)到视图的特定元素。因此,我重写了用于实例化 ViewModel 类 的 caliburns GetInstance 方法。在这个方法中,我用动态代理包装每个视图模型,然后 return 它:
protected override object GetInstance(Type serviceType, string key)
{
var instance = container.GetInstance(serviceType, key);
if (instance != null)
{
object ret = pg.CreateClassProxyWithTarget(instance.GetType(), (instance), new LoggingInterceptor());
return ret;
}
throw new Exception("Could not locate any instances.");
//return null;
}
不幸的是,这次更改后我的视图只显示
Cannot find view for Castle.Proxies.FirstViewModelProxy.
因为我知道castles dynamicproxy将字符串"Proxy"添加到新创建的类型的末尾,而caliburn会替换字符串末尾的Model一词,然后尝试使用该字符串找到相应的视图我添加了另一个 NameTransformer 规则:
public CaliburnBootstrapper()
{
LogManager.GetLog = type => new DebugLogger(type);
Initialize();
ViewLocator.NameTransformer.AddRule("ModelProxy$", string.Empty);
}
但这并没有改变任何东西。如何解决这个问题?
经过更多研究后,我发现自己如何做到这一点:Caliburn 允许交换负责视图模型名称转换的方法以查看。所以我所做的就是自己调用原始名称转换方法。当它没有 returns 任何东西时,我会尝试自己的逻辑。成功了。
Func<string, object, IEnumerable<string>> orig = ViewLocator.TransformName;
ViewLocator.TransformName = new Func<string,object,IEnumerable<string>>(
delegate(string a, object b )
{
IEnumerable<string> ret = orig(a,b);
if (ret.Count() > 0)
{
return ret;
}
a = Regex.Replace(a, "^Castle.Proxies", "CaliburnSample.Views");
a = Regex.Replace(a, "ModelProxy$", string.Empty);
a = Regex.Replace(a, "Model$", string.Empty);
return new string[] { a };
}
);
更新: 几乎一切正常。按钮按照惯例绑定到方法等。但不幸的是,属性通知不再起作用了。视图不再使用属性的新内容进行更新,尽管它们受 caliburn 约束:
INFO: [2015-12-09T11:36:30.2646933+01:00] Binding Convention Applied: Element TxtMsg.