C# 如何在MVVM中管理对象生命周期?
我正在开发一个使用C#和WPF构建的应用程序,它(糟糕地)实现了MVVM。工作分解如下:C# 如何在MVVM中管理对象生命周期?,c#,wpf,mvvm,C#,Wpf,Mvvm,我正在开发一个使用C#和WPF构建的应用程序,它(糟糕地)实现了MVVM。工作分解如下: 看法 演示文稿、位图、颜色等 动画(如果使用) 通过绑定到ViewModel的数据与ViewModel通信 通过在ViewModel上发出命令与ViewModel通信 视图模型 公开要由视图调用的命令 将数据处理功能委托给模型 定义UI行为 对视图没有直接(命名)依赖关系 通过调用模型中的方法与模型通信 可以通过订阅模型公开的事件来通知模型中的更改 模型 磁盘持久性、数据分析等 其他一切 不依赖
- 看法
- 演示文稿、位图、颜色等
- 动画(如果使用)
- 通过绑定到ViewModel的数据与ViewModel通信
- 通过在ViewModel上发出命令与ViewModel通信
- 视图模型
- 公开要由视图调用的命令
- 将数据处理功能委托给模型
- 定义UI行为
- 对视图没有直接(命名)依赖关系
- 通过调用模型中的方法与模型通信
- 可以通过订阅模型公开的事件来通知模型中的更改
- 模型
- 磁盘持久性、数据分析等
- 其他一切
- 不依赖于ViewModel
DataContext
),viewmodels需要对模型的引用来委派工作,模型通常需要将状态的某些外部变化通知viewmodels
我们有两个循环参考问题,VIEW模型位于中间。因此,此应用程序会遇到内存消耗问题,因为正在创建WPF实体并将其与模型中的某些数据段关联,并且这些实体永远不会被清理(直到程序终止)
这应该怎么处理似乎需要定义一个所有权图,这样当事件处理程序不再相关时,这些组件中的一个或多个负责断开它们之间的连接,你的问题没有提供足够的关于实例化内容的信息,我怀疑在不深入挖掘所有代码的情况下是否有可能解决这个问题 第一:这是一个非常糟糕的MVVM,因为这里违反了层和关注点的分离 我建议先解决这个问题。 您的问题可能是根本不了解XAML和实例化(无意冒犯) 在不涉及体系结构的情况下,您需要对应用程序进行概要分析,以查看哪些对象被实例化了多少次(内存热点),查看这些对象是在哪个GC生成中也是很有趣的,因为这可能表明存在一些严重的(手动)内存管理问题 事件处理程序往往会造成泄漏。因此,可采用弱参考模式:
一个好的MVVM具有某种生命周期管理,它还可以将服务器作为DI和IoC容器来处理复杂的生命周期场景好的,我想您已经直接将它们一起使用了 如果没有任何缓存视图,那么为什么内存使用率很高 MVVM应用程序中不可能存在内存问题(即使是架构不好的应用程序) 你有哪些静态项目 您是否曾经使用此代码来调查wpf应用程序绑定的当前情况
private static IList<BindingInfo> getReflectPropertyDescriptorInfo()
{
var results = new List<BindingInfo>();
var reflectTypeDescriptionProvider = typeof(PropertyDescriptor).Module.GetType("System.ComponentModel.ReflectTypeDescriptionProvider");
var propertyCacheField = reflectTypeDescriptionProvider.GetField("_propertyCache",
BindingFlags.Static | BindingFlags.NonPublic);
if (propertyCacheField == null)
throw new NullReferenceException("`ReflectTypeDescriptionProvider._propertyCache` not found");
var propertyCacheItems = propertyCacheField.GetValue(null) as Hashtable;
if (propertyCacheItems == null)
return results;
var valueChangedHandlersField = typeof(PropertyDescriptor).GetField("valueChangedHandlers",
BindingFlags.Instance | BindingFlags.NonPublic);
if (valueChangedHandlersField == null)
return results;
foreach (DictionaryEntry entry in propertyCacheItems)
{
var properties = entry.Value as PropertyDescriptor[];
if (properties == null)
continue;
foreach (var property in properties)
{
var valueChangedHandlers = valueChangedHandlersField.GetValue(property) as Hashtable;
if (valueChangedHandlers != null && valueChangedHandlers.Count != 0)
results.Add(new BindingInfo
{
TypeName = entry.Key.ToString(),
PropertyName = property.Name,
HandlerCount = valueChangedHandlers.Count
});
}
}
return results;
}
private静态IList getReflectPropertyDescriptorInfo()
{
var results=新列表();
var reflectTypeDescriptionProvider=typeof(PropertyDescriptor).Module.GetType(“System.ComponentModel.reflectTypeDescriptionProvider”);
var propertyCacheField=reflectTypeDescriptionProvider.GetField(“\u propertyCache”,
BindingFlags.Static | BindingFlags.NonPublic);
if(propertyCacheField==null)
抛出新的NullReferenceException(`ReflectTypeDescriptionProvider.\u propertyCache`not found');
var propertyCacheItems=propertyCacheField.GetValue(null)作为哈希表;
如果(propertyCacheItems==null)
返回结果;
var valueChangedHandlersField=typeof(PropertyDescriptor).GetField(“valueChangedHandlers”,
BindingFlags.Instance | BindingFlags.NonPublic);
如果(valueChangedHandlersField==null)
返回结果;
foreach(propertyCacheItems中的DictionaryEntry条目)
{
var properties=entry.Value作为PropertyDescriptor[];
如果(属性==null)
继续;
foreach(属性中的var属性)
{
var valueChangedHandlers=valueChangedHandlersField.GetValue(属性)作为哈希表;
if(valueChangedHandlers!=null&&valueChangedHandlers.Count!=0)
结果。添加(新绑定信息
{
TypeName=entry.Key.ToString(),
PropertyName=property.Name,
HandlerCount=valueChangedHandlers.Count
});
}
}
返回结果;
}
通过这段代码,您可以找到内存中的绑定是什么?“viewmodels需要对视图的引用才能更新视图状态(通常该引用由作为WPF的DataContext的viewmodel进行引用)。”-此时不存在依赖关系,因为视图不知道DataContext中的内容,而ViewModel也不知道有关视图的任何内容,因此它不是视图的in-ViewModel的明确依赖关系
当您需要将ViewModel分配给DataContext时,就得到了依赖关系,并且View依赖于ViewModel(不需要这样做,因为可以使用IViewModel代替ViewModel)
即使使用ViewModel-first方法,您实际上并没有视图,您也有由视图实现的IView契约
class ContentViewModel{
IView view;
public ContentViewModel(IContentAView view)
{
View = view;
View.ViewModel = this;
如果您使用容器作为Unity,并且视图模型或视图将在每个tim实例化