简体   繁体   English

.NET 5.0 SettingsSerializeAs.Binary 已过时

[英].NET 5.0 SettingsSerializeAs.Binary obsolete

    /// Serialization
    /// Code 2012.05.23, [...] following Jani Giannoudis' examples
    /// CodeProject Article "User Settings Applied", 
    /// http://www.codeproject.com/Articles/25829/User-Settings-Applied
    /// </summary>

I'm using the above mentioned codeproject.com Code since a number of years successfully in different projects.我使用上面提到的 codeproject.com 代码多年来在不同的项目中取得了成功。 A few days ago, I converted one of those projects from .NET 4.x to .NET 6.0 and the unmodified code immediately stopped working (details below) for example in the following snippet:几天前,我将其中一个项目从 .NET 4.x 转换为 .NET 6.0,未修改的代码立即停止工作(详情如下),例如以下代码段:

        // DataGridColumnSetting[] is based on System.Configuration.ApplicationSettingsBase
        // https://learn.microsoft.com/en-us/dotnet/api/system.configuration.applicationsettingsbase?view=dotnet-plat-ext-6.0
        private DataGridColumnSetting[] OriginalColumnSettings
        {
            get
            {
                return LoadValue(
                    Name,
                    typeof(DataGridColumnSetting[]),
                    SettingsSerializeAs.Binary,
                    null) as DataGridColumnSetting[];
            }
        }

Throwing a投掷一个

System.NotSupportedException
  HResult=0x80131515
  Message=BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information.
  Source=System.Configuration.ConfigurationManager
  StackTrace:
   at System.Configuration.SettingsProperty..ctor(String name, Type propertyType, SettingsProvider provider, Boolean isReadOnly, Object defaultValue, SettingsSerializeAs serializeAs, SettingsAttributeDictionary attributes, Boolean throwOnErrorDeserializing, Boolean throwOnErrorSerializing)
   at MyNamespace.Serialization.Setting.CreateSettingProperty(String name, Type type, SettingsSerializeAs serializeAs, Object defaultValue) in [...]MyNamespace\Serialization\Setting.cs:line 111

Since the very same code is working well in a .NET 4.8 project, I tried to find hints in the web and found由于完全相同的代码在 .NET 4.8 项目中运行良好,我试图在 web 中找到提示并找到

https://learn.microsoft.com/en-us/do.net/core/compatibility/core-libraries/5.0/binaryformatter-serialization-obsolete (and a few others) also saying https://learn.microsoft.com/en-us/do.net/core/compatibility/core-libraries/5.0/binaryformatter-serialization-obsolete (和其他一些)也说

Warning "The BinaryFormatter type is dangerous and is not recommended for data processing. Applications should stop using BinaryFormatter as soon as possible, even if they believe the data they're processing to be trustworthy. BinaryFormatter is insecure and can't be made secure."警告“BinaryFormatter 类型是危险的,不建议用于数据处理。应用程序应尽快停止使用 BinaryFormatter,即使他们认为他们正在处理的数据是值得信赖的。BinaryFormatter 是不安全的,无法保证安全。 “

Actual Question: Anyone else having the very same issue using the same code (from the above mentioned CodeProject Article "User Settings Applied").实际问题:使用相同代码(来自上面提到的 CodeProject 文章“应用的用户设置”)的任何其他人都有同样的问题。 (If not, I would start modifying (my personal flavor of) that code, and if successful post an answer to my question assuming others might hopefully benefit.) (如果没有,我会开始修改(我个人的风格)该代码,如果成功发布我的问题的答案,假设其他人可能会受益。)

Okay, apparently using JSON instead of Binary works as expected here in anhttp://www.codeproject.com/Articles/25829/User-Settings-Applied context (in.Net4.x as well as.Net 6).好的,显然使用 JSON 而不是 Binary 在http://www.codeproject.com/Articles/25829/User-Settings-Applied上下文(in.Net4.x 以及 .Net 6)中按预期工作。 The basic concept there is having a particular Serialization class for each UI Control one wants to handle.那里的基本概念是为每个想要处理的 UI 控件都有一个特定的序列化 class。 And only some of the article samples are using the deprecated SettingsSerializeAs.Binary , for example the one made for WPF DataGrid controls.并且只有一些文章示例使用已弃用的SettingsSerializeAs.Binary ,例如为 WPF DataGrid控件制作的示例。 The concept modification that works for me is using (NuGet) Newtonsoft.Json for serialization there.对我有用的概念修改是使用 (NuGet) Newtonsoft.Json在那里进行序列化。 The typical pattern part where the article author is using SettingsSerializeAs as quoted in the question is now using SettingsSerializeAs.String instead of Binary :文章作者使用问题中引用的SettingsSerializeAs的典型模式部分现在使用SettingsSerializeAs.String而不是Binary

private string OriginalColumnSettings
{
    get
    {
        return LoadValue(
                    Name,
                    typeof(string),
                    SettingsSerializeAs.String,
                    defaultValue: null) as string;
    }
}

Full real world (WPF) Sample for both.Net4.8 as well as.Net6: .Net4.8 和 .Net6 的完整真实世界 (WPF) 示例:

using Newtonsoft.Json;
using NLog;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace WhatEverNamespace.Serialization
{
    /// <summary>
    /// Serialization
    /// Code 2012.05.23, [...] following Jani Giannoudis' examples
    /// CodeProject Article "User Settings Applied", 
    /// http://www.codeproject.com/Articles/25829/User-Settings-Applied
    /// </summary>
    public class DataGridSetting : Setting
    {
        public static readonly DependencyProperty SettingProperty =
            DependencyProperty.RegisterAttached(
                "Setting",
                typeof(string),
                typeof(DataGridSetting),
                new FrameworkPropertyMetadata(OnDataGridSettingChanged));

        #region Fields

        private static readonly Logger log = LogManager.GetCurrentClassLogger();

        private readonly DataGrid dataGrid;
        private readonly IList<DataGridColumn> dataGridColumns = new List<DataGridColumn>();
        private bool isLoaded;

        private readonly string name;
        private bool useWidth = true;
        private bool useDisplayIndex = true;

        #endregion Fields

        #region Constructors

        public DataGridSetting(DataGrid dataGrid) :
            this(dataGrid?.Name, dataGrid)
        {
        }

        public DataGridSetting(string name, DataGrid dataGrid)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentNullException(nameof(name));

            this.name = name;
            this.dataGrid = dataGrid ?? throw new ArgumentNullException(nameof(dataGrid));
        }

        #endregion Constructors

        #region Properties

        public string Name { get { return name; } }

        public DataGrid DataGrid { get { return dataGrid; } }

        public bool UseWidth
        {
            get { return useWidth; }
            set { useWidth = value; }
        }

        public bool UseDisplayIndex
        {
            get { return useDisplayIndex; }
            set { useDisplayIndex = value; }
        }

        public override bool HasChanged
        {
            get
            {
                var json = OriginalColumnSettings;
                if (string.IsNullOrWhiteSpace(json))
                    return false;

                var originalColumnSettings = JsonConvert.DeserializeObject<DataGridColumnSetting[]>(json);
                DataGridColumnSetting[] columnSettings = ColumnSettings;
                if (json.Length != columnSettings.Length)
                    return true;

                for (int i = 0; i < originalColumnSettings.Length; i++)
                {
                    if (!originalColumnSettings[i].Equals(columnSettings[i]))
                        return true;
                }

                return false;
            }
        }

        private string OriginalColumnSettings
        {
            get
            {
                return LoadValue(
                    Name,
                    typeof(string),
                    SettingsSerializeAs.String,
                    defaultValue: null) as string;
            }
        }

        private DataGridColumnSetting[] ColumnSettings
        {
            get
            {
                if (dataGrid?.Columns.Any() != true)
                    return null;

                IList<DataGridColumnSetting> columnSettings =
                    new List<DataGridColumnSetting>(dataGrid.Columns.Count);
                foreach (DataGridColumn dataGridColumn in dataGrid.Columns)
                {
                    int index = dataGridColumns.IndexOf(dataGridColumn);
                    int displayIndex = dataGridColumn.DisplayIndex;
                    DataGridColumnSetting columnSetting = new DataGridColumnSetting
                    {
                        Index = index,
                        DisplayIndex = displayIndex,
                        Width = dataGridColumn.ActualWidth
                    };
                    columnSettings.Add(columnSetting);
                }

                return columnSettings.ToArray();
            }
        }

        #endregion Properties

        #region Methods

        public static string GetSetting(DependencyObject dependencyObject)
        {
            return dependencyObject?.GetValue(SettingProperty) as string;
        }

        public static void SetSetting(DependencyObject dependencyObject, string settingKey)
        {
            dependencyObject?.SetValue(SettingProperty, settingKey);
        }

        public override void Load()
        {
            // Initialized event does not work since it's running too early in a WPF DataGrid
            // ("dataGrid.Initialized += DataGridInitialized" in Jani's ListViewSettings.cs)
            if (isLoaded == false)
                SetupDataGridColumns();

            try
            {
                DataGrid dataGrid = this.dataGrid;
                if (dataGrid?.Columns.Any() != true)
                    return;

                var json = OriginalColumnSettings;
                var columnSettings = JsonConvert.DeserializeObject<DataGridColumnSetting[]>(json);
                if (columnSettings?.Any() != true)
                    return;

                for (int displayIndex = 0; displayIndex < columnSettings.Length; displayIndex++)
                {
                    DataGridColumnSetting columnSetting = columnSettings[displayIndex];
                    if (columnSetting.Index < 0 || columnSetting.Index >= dataGridColumns.Count)
                        continue;

                    DataGridColumn dataGridColumn = dataGridColumns[columnSetting.Index];
                    if (useWidth)
                        dataGridColumn.Width = new DataGridLength(columnSetting.Width);

                    if (useDisplayIndex && columnSetting.Index != columnSetting.DisplayIndex)
                        dataGridColumn.DisplayIndex = columnSetting.DisplayIndex;
                }
            }
            catch
            {
                if (ThrowOnErrorLoading)
                    throw;
            }
        }

        public override void Save()
        {
            try
            {
                DataGridColumnSetting[] columnSettings = ColumnSettings;
                if (columnSettings == null)
                    return;

                var json = JsonConvert.SerializeObject(columnSettings);

                SaveValue(
                    Name,
                    typeof(string),
                    SettingsSerializeAs.String,
                    json,
                    null);
            }
            catch
            {
                if (ThrowOnErrorSaving)
                    throw;
            }
        }

        public override string ToString()
        {
            return string.Concat(name, " (DataGrid)");
        }

        private void SetupDataGridColumns()
        {
            dataGridColumns.Clear();

            if (dataGrid == null)
                return;

            if (dataGrid.Columns.Count > 0)
                isLoaded = true;
            else
                return;

            for (int i = 0; i < dataGrid.Columns.Count; i++)
            {
                dataGridColumns.Add(dataGrid.Columns[i]);
            }
        }

        private static void OnDataGridSettingChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            if (!(dependencyObject is DataGrid dataGrid))
            {
                log.Warn(CultureInfo.InvariantCulture,
                    "{0}.{1}(): invalid property attachment",
                    nameof(DataGridSetting),
                    nameof(OnDataGridSettingChanged));
                return;
            }

            // search on the parent-tree for application settings
            ApplicationSettings applicationSettings = FindParentSettings(dependencyObject);
            if (applicationSettings == null)
            {
                log.Warn(CultureInfo.InvariantCulture,
                    "{0}.{1}(): missing application settings in parent hierarchy",
                    nameof(DataGridSetting),
                    nameof(OnDataGridSettingChanged));
                return;
            }

            applicationSettings.Settings.Add(new DataGridSetting(dataGrid));
        }

        private static ApplicationSettings FindParentSettings(DependencyObject element)
        {
            while (element != null)
            {
                if (element.ReadLocalValue(
                    DependencyPropertySetting.ApplicationSettingsProperty) is ApplicationSettings applicationSettings)
                    return applicationSettings;
                element = LogicalTreeHelper.GetParent(element);
            }
            return null;
        }

        #endregion Methods
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM