Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在MVVM中管理对象生命周期?_C#_Wpf_Mvvm - Fatal编程技术网

C# 如何在MVVM中管理对象生命周期?

C# 如何在MVVM中管理对象生命周期?,c#,wpf,mvvm,C#,Wpf,Mvvm,我正在开发一个使用C#和WPF构建的应用程序,它(糟糕地)实现了MVVM。工作分解如下: 看法 演示文稿、位图、颜色等 动画(如果使用) 通过绑定到ViewModel的数据与ViewModel通信 通过在ViewModel上发出命令与ViewModel通信 视图模型 公开要由视图调用的命令 将数据处理功能委托给模型 定义UI行为 对视图没有直接(命名)依赖关系 通过调用模型中的方法与模型通信 可以通过订阅模型公开的事件来通知模型中的更改 模型 磁盘持久性、数据分析等 其他一切 不依赖

我正在开发一个使用C#和WPF构建的应用程序,它(糟糕地)实现了MVVM。工作分解如下:

  • 看法

    • 演示文稿、位图、颜色等
    • 动画(如果使用)
    • 通过绑定到ViewModel的数据与ViewModel通信
    • 通过在ViewModel上发出命令与ViewModel通信
  • 视图模型

    • 公开要由视图调用的命令
    • 将数据处理功能委托给模型
    • 定义UI行为
    • 对视图没有直接(命名)依赖关系
    • 通过调用模型中的方法与模型通信
    • 可以通过订阅模型公开的事件来通知模型中的更改
  • 模型

    • 磁盘持久性、数据分析等
    • 其他一切
    • 不依赖于ViewModel
不幸的是,这导致了循环引用,因为视图需要对viewmodels的引用来引发事件和触发命令,viewmodels需要对视图的引用来更新视图状态(通常该引用是由一个viewmodel作为WPF的
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实例化