【问题标题】:.NET 5.0 SettingsSerializeAs.Binary obsolete.NET 5.0 SettingsSerializeAs.Binary 已过时
【发布时间】:2022-12-29 01:05:56
【问题描述】:
    /// Serialization
    /// Code 2012.05.23, [...] following Jani Giannoudis' examples
    /// CodeProject Article "User Settings Applied", 
    /// http://www.codeproject.com/Articles/25829/User-Settings-Applied
    /// </summary>

多年来,我一直在不同的项目中成功使用上面提到的 codeproject.com 代码。 几天前,我将其中一个项目从 .NET 4.x 转换为 .NET 6.0,未修改的代码立即停止工作(详情如下),例如以下 sn-p:

        // 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[];
            }
        }

投掷一个

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

由于完全相同的代码在 .NET 4.8 项目中运行良好,我试图在网络上查找提示并找到

https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/5.0/binaryformatter-serialization-obsolete (和其他一些人)也说

警告 “BinaryFormatter 类型是危险的,不推荐用于数据处理。应用程序应尽快停止使用 BinaryFormatter,即使他们认为他们正在处理的数据是值得信赖的。BinaryFormatter 是不安全的,无法保证安全。”

实际问题:使用相同代码(来自上面提到的 CodeProject 文章“应用的用户设置”)的任何其他人都有相同的问题。 (如果没有,我会开始修改(我个人的风格)该代码,如果成功发布我的问题的答案,假设其他人可能会受益。)

【问题讨论】:

  • “因为完全相同的代码在 .NET 4.8 项目中运行良好”- 公平地说,您上面的代码清单在构建之间可能看起来是相同的,并非所有代码都是您的,因为它具有您无法控制的外部依赖项。 .NET Core 从来都不是 .NET Framework 的 1:1,而 .NET 5.x+ 仍然如此。出于这个原因,您应该在从 .NET Framework 迁移之前考虑所有影响 ---> .NET Core; .NET 5+
  • 你所能做的就是关注Recommended action你引用的每一页
  • 是的,我阅读了我发布的内容。看看和比较其他人使用那个(非常有用的)文章代码可能做了什么会很有趣:)

标签: c# serialization .net-6.0 .net-4.8


【解决方案1】:

好的,显然使用 JSON 而不是 Binary 在 http://www.codeproject.com/Articles/25829/User-Settings-Applied 上下文中(在 .Net4.x 和 .Net 6 中)按预期工作。 那里的基本概念是为每个想要处理的 UI 控件提供一个特定的序列化类。并且只有一些文章示例使用已弃用的 SettingsSerializeAs.Binary,例如为 WPF 制作的 DataGridcontrols。对我有用的概念修改是使用 (NuGet) Newtonsoft.Json 在那里进行序列化。 问题中引用的文章作者使用 SettingsSerializeAs 的典型模式部分现在使用 SettingsSerializeAs.String 而不是 Binary

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

.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
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-22
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多