Spring.net AOP 似乎干扰 WPF 数据绑定
我已经使用 Spring.net 依赖注入框架更新了我的项目。然后我继续集成 AOP 以启用简单的日志记录/跟踪机制。我的 app.config 中存在一些循环依赖问题,但我解决了:
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<object id="loggingAroundAdvice" type="SetupBuilder.LoggingAroundAdvice"/>
<object id="myServiceObjectTarget" type="SetupBuilder.SetupBuilderModelView, SetupBuilder">
<!--<object name="Model" type="SetupBuilder.SetupBuilderModelView, SetupBuilder">-->
<constructor-arg index="0" ref="MasterData"/>
<property name="FileSelection" ref="FileSelection"/>
<property name="Persistence" ref="Persistence"/>
<property name="Distributor" ref="Distributor"/>
<property name="Document" ref="Document"/>
<property name="StatusWindow" ref="StatusWindow"/>
</object>
<object name="Model" type="Spring.Aop.Framework.ProxyFactoryObject">
<property name="target" ref="myServiceObjectTarget"/>
<property name="interceptorNames">
<list>
<value>loggingAroundAdvice</value>
</list>
</property>
</object>
<object name="MasterData" type="VMRedistMasterData.Implementation.VMRedistMasterDataImpl, VMRedistMasterData"/>
<object name="FileSelection" type="SetupBuilder.OpenAndSaveDialog, SetupBuilder"/>
<object name="Persistence" type="VMRedistDelivery.Implementation.Persistence.DeliveryPersistence, VMRedistDelivery"/>
<object name="Distributor" type="VMRedistDelivery.Implementation.Distribution.Distributor, VMRedistDelivery"/>
<object name="Document" type="Word2010ReleaseDocument.Word2010ReleaseDocument, Word2010ReleaseDocument"/>
<object name="StatusWindow" type="SetupBuilder.WpfStatusWindow, SetupBuilder">
<constructor-arg index="0" ref="Model"/>
</object>
</objects>
我的类如下所示:
public interface ISetupBuilderModelViewDependencies
{
IVMRedistMasterData MasterData { get; set; }
IFileSelection FileSelection { get; set; }
IVMRedistPersistence Persistence { get; set; }
IVMRedistDistributor Distributor { get; set; }
IVMRedistReleaseDocument Document { get; set; }
IStatusWindow StatusWindow { get; set; }
}
public class SetupBuilderModelView : ISetupBuilderModelView, ISetupBuilderModelViewDependencies, INotifyPropertyChanged
{
...
public string Customer
{
get { return customer; }
set
{
customer = value;
FirePropertyChanged("Customer");
}
}
...
}
这是分配给我的主 WPF 窗口的 Model 对象:
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
var context = ContextRegistry.GetContext();
var setupBuilderWindow = new SetupBuilderWindow(context.GetObject("Model") as ISetupBuilderModelView);
// SetupBuilderWindow needs an ISetupBuilderModelView argument.
setupBuilderWindow.Show();
}
}
但是,如果“Model”对象发生更改,我的 WPF 窗口将不再更新!财产发生变化。 PropertyChanged 事件被抛出,并且有人已订阅该事件。但没有人尝试获取属性值。跟踪/日志记录机制有效,get_Customer()
仅在启动时调用一次,然后就不再调用。我不明白。 Spring.Aop.Framework.ProxyFactoryObject 应该将每个事件从目标对象传输到所有订阅者,不是吗?如果这不是问题并且事件到来,那么问题出在属性上吗?代理对象是否缓存目标的属性?我就是不明白。
app.config 中的注释行没有 AOP。如果我注释上面的行并取消注释该行,则一切正常。
如果您有任何想法,请告诉我。我希望我提供了足够但不是太多的信息。如果您需要更多信息,我很乐意提供。
I have updated my project with the Spring.net Dependency Injection Framwork. Then I continued with integrating AOP to enable a simple logging/trace mechanism. I had some problems with a circular dependendy in my app.config, but I worked it out:
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<object id="loggingAroundAdvice" type="SetupBuilder.LoggingAroundAdvice"/>
<object id="myServiceObjectTarget" type="SetupBuilder.SetupBuilderModelView, SetupBuilder">
<!--<object name="Model" type="SetupBuilder.SetupBuilderModelView, SetupBuilder">-->
<constructor-arg index="0" ref="MasterData"/>
<property name="FileSelection" ref="FileSelection"/>
<property name="Persistence" ref="Persistence"/>
<property name="Distributor" ref="Distributor"/>
<property name="Document" ref="Document"/>
<property name="StatusWindow" ref="StatusWindow"/>
</object>
<object name="Model" type="Spring.Aop.Framework.ProxyFactoryObject">
<property name="target" ref="myServiceObjectTarget"/>
<property name="interceptorNames">
<list>
<value>loggingAroundAdvice</value>
</list>
</property>
</object>
<object name="MasterData" type="VMRedistMasterData.Implementation.VMRedistMasterDataImpl, VMRedistMasterData"/>
<object name="FileSelection" type="SetupBuilder.OpenAndSaveDialog, SetupBuilder"/>
<object name="Persistence" type="VMRedistDelivery.Implementation.Persistence.DeliveryPersistence, VMRedistDelivery"/>
<object name="Distributor" type="VMRedistDelivery.Implementation.Distribution.Distributor, VMRedistDelivery"/>
<object name="Document" type="Word2010ReleaseDocument.Word2010ReleaseDocument, Word2010ReleaseDocument"/>
<object name="StatusWindow" type="SetupBuilder.WpfStatusWindow, SetupBuilder">
<constructor-arg index="0" ref="Model"/>
</object>
</objects>
My class looks like this:
public interface ISetupBuilderModelViewDependencies
{
IVMRedistMasterData MasterData { get; set; }
IFileSelection FileSelection { get; set; }
IVMRedistPersistence Persistence { get; set; }
IVMRedistDistributor Distributor { get; set; }
IVMRedistReleaseDocument Document { get; set; }
IStatusWindow StatusWindow { get; set; }
}
public class SetupBuilderModelView : ISetupBuilderModelView, ISetupBuilderModelViewDependencies, INotifyPropertyChanged
{
...
public string Customer
{
get { return customer; }
set
{
customer = value;
FirePropertyChanged("Customer");
}
}
...
}
Here is the Model object assigned to my main WPF window:
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
var context = ContextRegistry.GetContext();
var setupBuilderWindow = new SetupBuilderWindow(context.GetObject("Model") as ISetupBuilderModelView);
// SetupBuilderWindow needs an ISetupBuilderModelView argument.
setupBuilderWindow.Show();
}
}
But if changes in the "Model" object occur, my WPF window is not updated anymore! The Property changed. The PropertyChanged event is thrown and someone has subscribed it. But noone tries to get the Property values. The trace/logging mechanism works, get_Customer()
is only called once at startup, then never again. I don't get it. The Spring.Aop.Framework.ProxyFactoryObject
should transfer every event from the target object to all subscribers, shouldn't it? If that's not the problem and the event arrives, is the problem in the property? Is the Proxy object caching the target's properties? I just don't get it.
The commented line in app.config was without AOP. If I comment the line above and uncomment that line, everything works normal.
If you have any idea, please let me know. I hope I provided enough but not too much information. If you need further information, i would be happy to provide it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你的最后一条评论让我想起这个问题。在他的回答中,Mark Pollack(Spring 开发人员)建议将其放入您的配置中:
这将创建一个基于继承的代理。默认情况下,Spring AOP 为您的类创建一个基于组合的代理,因此不会拦截任何内部方法,因为实例具有对其自身的引用,而不是对其 Spring 创建的代理的引用。
请注意,事件不会自动从目标传播到代理。这(可能)就是为什么模型中的更改不会传播到 wpf 窗口的原因:模型触发属性更改,但您的窗口绑定到代理。在问题 spring-aop-mvvm-foundation-propertychanged 我试图解释对此进行了详细说明,并提出了一个(hackish)解决方法。
Your last comment reminds me of this question. In his answer, Mark Pollack (Spring developer) suggests to put this in your configuration:
This will create an inheritance based proxy. By default, Spring AOP creates a composition based proxy for your class, so any internal methods are not intercepted, because an instance has a reference to itself and not to its Spring-created proxy.
Note that events aren't automatically propagated from target to proxy. This is (probably) why the changes from your model don't propagate to your wpf window: the model fires a property change, but your window is bound to the proxy. In the question spring-aop-mvvm-foundation-propertychanged I've tried to explain this in detail and have proposed a (hackish) work-around.