在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属性来指定静态未知的类型。”
我无法显示该课程的完整路径,但这是我的课程之一。我没有为该类添加任何属性,但是我不认为它是我正在研究的控件的一部分。