“类型*不是预期的。请使用XmlInclude或SoapInclude属性指定静态未知的类型。”

时间:2018-10-03 14:29:53

标签: c# wpf serialization xml-serialization

在WPF应用程序中,我有一个DataGrid,它可以从数据库中获取值,这些值用作机器的机器人组件的配置参数。

我正在尝试添加一项功能,以使用XML序列化(以前从未使用过)将网格中的值导入XML文档/从XML文档导入/导出(我以前从未使用过),但是遇到了一些问题,我无法理解我的生活。

我有一个Export()方法,应注意将值导出到XML文档:

public void Export()
    {
        XmlSerializer serialiser = new XmlSerializer(MasterDataGrid.ItemsSource.GetType());

        using (TextWriter writer = new StreamWriter("output.txt"))
        {
            serialiser.Serialize(writer, MasterDataGrid.ItemsSource);
            writer.Close();
        }


    }

这是定义MasterDataGrid内容的类:

[Serializable]
[XmlRoot]
public class CmcdConfigurationParameter : INotifyPropertyChanged, IDisposable
{
    [XmlElement(ElementName = "Configuration Parameter ID")]
    [Key] public Guid ConfigurationParameterID { get; set; }

    [XmlElement(ElementName = "Owning Device")]
    [ForeignKey("OwningDevice")] public Guid DeviceDefinitionID { get; set; }
    [XmlElement]
    public virtual CmcdDeviceDefinition OwningDevice { get; set; }

    [XmlElement(ElementName = "Name")]
    public string Name { get; set; }

    [XmlElement(ElementName = "Type Assembly Qualified Name")]
    public string TypeAssemblyQualifiedName { get; set; }

    private string _storedValue;
    [XmlElement(ElementName = "Stored Value")]
    public string StoredValue
    {
        get { return _storedValue;}
        set
        {
            _storedValue = value;
        }
    }

    [NotMapped]
    [XmlElement(ElementName = "Value")]
    public string Value
    {
        get { return StoredValue; }
        set { SetValue(value); }
    }


    private string _temporaryValueFromUser;
    [NotMapped]
    [XmlElement(ElementName = "Temporary Value")]
    public string TemporaryValueFromUser
    {
        get { return _temporaryValueFromUser; }
        set { _temporaryValueFromUser = value; }
    }

    public string Minimum { get; set; }
    public string Maximum { get; set; }
    public string Units { get; set; }
    public string DefaultValue { get; set; }
    public string Description { get; set; }
    public string DisplayName { get; set; }

    public EmcdConfigurationParameterType ConfigurationParameterType { get; set; }

    public virtual List<CmcdConfigurationParameterChangeLog>
         ChangeLogs
    {
        get;
        set;
    } //Need to confirm what is required to set up this relationship, is foreign key relationship needed?

    public CmcdConfigurationParameter(string strName)
    {
        ConfigurationParameterID = Guid.NewGuid();
        Name = strName;
    }

    public CmcdConfigurationParameter()
    {
    }

    private void ConfirmValueAboveMin<T>(T objNewValue)
    {
        if (Minimum != null)
        {
            var min = Convert.ChangeType(Minimum, Type.GetType(TypeAssemblyQualifiedName));

            var iCompareAgainstMinimumResult = ((IComparable) objNewValue).CompareTo((IComparable) min);

            if (iCompareAgainstMinimumResult < 0)
                throw new ArgumentException(
                    "CmcdConfigurationParameter.SetValue() failed because argument was below the minimum allowed.");
        }
    }

    private void ConfirmValueBelowMax(IComparable objNewValue)
    {
        if (Maximum != null)
        {
            var max = Convert.ChangeType(Maximum, Type.GetType(TypeAssemblyQualifiedName));

            var iCompareAgainstMaximumResult = objNewValue.CompareTo((IComparable) max);

            if (iCompareAgainstMaximumResult > 0)
                throw new ArgumentException(
                    "CmcdConfigurationParameter.SetValue() failed because argument was above the maximum allowed.");
        }
    }

    private bool IsValueSameAsExisting(string objNewValue)
    {
        if (Value != null)
        {
            var iCompareAgainstCurrentValue = ((IComparable) objNewValue).CompareTo(Value);

            if (iCompareAgainstCurrentValue == 0)
                return true;
        }

        return false;
    }

    public void SetValue(string objNewValueAsString, string changedBy = "unknown")
    {
        if (!IsValueSameAsExisting(objNewValueAsString))
        {

            if (TypeAssemblyQualifiedName == null)
            {
                StoredValue = objNewValueAsString;
                return;
            }

            try
            {
                var objNewValue = Convert.ChangeType(objNewValueAsString, Type.GetType(TypeAssemblyQualifiedName));
            }
            catch
            {
                throw new ArgumentException(string.Format(
                    "CmcdConfigurationParameter.SetValue was unable to convert the string value to its actual type. Expected type was {0}.",
                    TypeAssemblyQualifiedName));
            }

            ConfirmValueAboveMin(objNewValueAsString);
            ConfirmValueBelowMax(objNewValueAsString);


            try
            {
                if (ChangeLogs == null)
                    ChangeLogs = new List<CmcdConfigurationParameterChangeLog>();
            }
            catch (ObjectDisposedException e)
            {
                Console.WriteLine(e);
            }


            ChangeLogs?.Add(new CmcdConfigurationParameterChangeLog
            {
                ConfigurationParameterChangeLogID = Guid.NewGuid(),
                DateChanged = DateTime.Now,
                OwningConfigParameter = this,
                OldValue = Value,
                NewValue = objNewValueAsString,
                ChangedBy = changedBy
            });
            //TemporaryValueFromUser = Convert.ToString(objNewValueAsString);
            //ORIGINAL
            StoredValue = Convert.ToString(objNewValueAsString);
        }
    }

    public dynamic GetValue<T>()
    {
        if (Type.GetType(TypeAssemblyQualifiedName).IsEnum)
            return Enum.Parse(Type.GetType(TypeAssemblyQualifiedName), Value);
        return Convert.ChangeType(Value, Type.GetType(TypeAssemblyQualifiedName));
    }

    public override string ToString()
    {
        return Name;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string property = "")
    {
        var handler = PropertyChanged;
        handler?.Invoke(this, new PropertyChangedEventArgs(property));
    }

    public void Dispose()
    {

    }

    //This is required for Entity Framework to map the private property StoredValue (by default EF will not map non-public properties)
    public static readonly Expression<Func<CmcdConfigurationParameter, string>> StoredValueExpression =
        p => p.StoredValue;
}

很抱歉将整个课程都包括在内。我知道很多东西,但是我绝对不知道如何标记该类以进行序列化,因此我想将所有内容都张贴出来,这样就不会意外遗漏一些重要内容。我一般对序列化和属性都不熟悉,所以我认为类可能是问题的根源。

因此,在调用Export()方法时,出现以下错误:

  

“类型System.Data.Entity.DynamicProxies.CmcdConfigurationPar_66DFCBBA0ADF57C8F10B1E857261CD31C86C9556A2A09017262FF2C56200C356是不期望的。使用XmlInclude或SoapInclude属性指定静态未知的类型。”

我不能说出这是什么意思。我以为一长串字母数字字符可能是数据库中“参数”之一的键,但是我什么也找不到。我认为也许序列化程序需要对单个元素而不是列表进行操作,但是在尝试序列化数据网格的特定元素时遇到了相同的错误。

我在这里迷路了,因此任何指导将不胜感激。

编辑

我认为我关闭了动态代理/延迟加载,现在错误有所不同。

  

“不希望使用类型“ CmcdPickerDefinition”。请使用XmlInclude或SoapInclude属性来指定静态未知的类型。”

我无法显示该课程的完整路径,但这是我的课程之一。我没有为该类添加任何属性,但是我不认为它是我正在研究的控件的一部分。

0 个答案:

没有答案