将新项添加到自定义类的可观察集合中



我有一组用于将JSON反序列化为的类。我的程序将定期查找对此 JSON 文件的更改,如果找到任何更改,将使用反射将新数据推送到这些类的属性。

我需要在成功更新后找到添加到 Item2 类(SocialExportJSON.SocialExportData.Item2)集合中的任何新项目。

我的 JSON 类看起来像这样(还有更多,但我想避免太大的代码墙):

public class Item2 : INotifyPropertyChanged
{
[JsonProperty("type")]
private string type;
public string Type
{
get
{
return type;
}
set
{
if (type != value)
{
type = value;
RaisePropertyChanged("Type");
}
}
}
[JsonProperty("id")]
private string id;
public string ID
{
get
{
return id;
}
set
{
if (id != value)
{
id = value;
RaisePropertyChanged("ID");
}
}
}
[JsonProperty("postedIso8601")]
private string postedIso8601;
public string PostedIso8601
{
get
{
return postedIso8601;
}
set
{
if (postedIso8601 != value)
{
postedIso8601 = value;
RaisePropertyChanged("PostedIso8601");
}
}
}
[JsonProperty("postedTimestamp")]
private object postedTimestamp;
public object PostedTimestamp
{
get
{
return postedTimestamp;
}
set
{
if (postedTimestamp != value)
{
postedTimestamp = value;
RaisePropertyChanged("PostedTimestamp");
}
}
}
[JsonProperty("engagement")]
private Engagement engagement;
public Engagement Engagement
{
get
{
return engagement;
}
set
{
if (engagement != value)
{
engagement = value;
RaisePropertyChanged("Engagement");
}
}
}
[JsonProperty("source")]
private Source2 source;
public Source2 Source
{
get
{
return source;
}
set
{
if (source != value)
{
source = value;
RaisePropertyChanged("Source");
}
}
}
[JsonProperty("author")]
private Author author;
public Author Author
{
get
{
return author;
}
set
{
if (author != value)
{
author = value;
RaisePropertyChanged("Author");
}
}
}
[JsonProperty("content")]
private Content content;
public Content Content
{
get
{
return content;
}
set
{
if (content != value)
{
content = value;
RaisePropertyChanged("Content");
}
}
}
[JsonProperty("location")]
private Location location;
public Location Location
{
get
{
return location;
}
set
{
if (location != value)
{
location = value;
RaisePropertyChanged("Location");
}
}
}
[JsonProperty("publication")]
private Publication publication;
public Publication Publication
{
get
{
return publication;
}
set
{
if (publication != value)
{
publication = value;
RaisePropertyChanged("Publication");
}
}
}
[JsonProperty("metadata")]
private Metadata metadata;
public Metadata Metadata
{
get
{
return metadata;
}
set
{
if (metadata != value)
{
metadata = value;
RaisePropertyChanged("Metadata");
}
}
}
//Event handling
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
//Console.WriteLine("Updated");
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
public class SocialExportData : INotifyPropertyChanged
{
[JsonProperty("dataType")]
private string dataType;
public string DataType
{
get
{
return dataType;
}
set
{
if (dataType != value)
{
dataType = value;
RaisePropertyChanged("DataType");
}
}
}
[JsonProperty("id")]
private int id;
public int ID
{
get
{
return id;
}
set
{
if (id != value)
{
id = value;
RaisePropertyChanged("ID");
}
}
}
[JsonProperty("story")]
private Story story;
public Story Story
{
get
{
return story;
}
set
{
if (story != value)
{
story = value;
RaisePropertyChanged("Story");
}
}
}
[JsonProperty("order")]
private string order;
public string Order
{
get
{
return order;
}
set
{
if (order != value)
{
order = value;
RaisePropertyChanged("Order");
}
}
}
[JsonProperty("lifetime")]
private string lifetime;
public string Lifetime
{
get
{
return lifetime;
}
set
{
if (lifetime != value)
{
lifetime = value;
RaisePropertyChanged("Lifetime");
}
}
}
[JsonProperty("maxAge")]
private int maxAge;
public int MaxAge
{
get
{
return maxAge;
}
set
{
if (maxAge != value)
{
maxAge = value;
RaisePropertyChanged("MaxAge");
}
}
}
[JsonProperty("maxSize")]
private int maxSize;
public int MaxSize
{
get
{
return maxSize;
}
set
{
if (maxSize != value)
{
maxSize = value;
RaisePropertyChanged("MaxSize");
}
}
}
[JsonProperty("consumeCount")]
private int consumeCount;
public int ConsumeCount
{
get
{
return consumeCount;
}
set
{
if (consumeCount != value)
{
consumeCount = value;
RaisePropertyChanged("ConsumeCount");
}
}
}
[JsonProperty("consumeInterval")]
private int consumeInterval;
public int ConsumeInterval
{
get
{
return consumeInterval;
}
set
{
if (consumeInterval != value)
{
consumeInterval = value;
RaisePropertyChanged("ConsumeInterval");
}
}
}
[JsonProperty("items")]
private ObservableCollection<Item2> items;
public ObservableCollection<Item2> Items
{
get
{
return items;
}
set
{
if (items != value)
{
items = value;
RaisePropertyChanged("Items");
}
}
}
//Event handling
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
//Console.WriteLine("Updated");
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
public class SocialExportJSON : INotifyPropertyChanged
{
[JsonProperty("id")]
private string id;
public string ID
{
get
{
return id;
}
set
{
if (id != value)
{
id = value;
RaisePropertyChanged("ID");
}
}
}
[JsonProperty("ttl")]
private int ttl;
public int TTL
{
get
{
return ttl;
}
set
{
if (ttl != value)
{
ttl = value;
RaisePropertyChanged("TTL");
}
}
}
[JsonProperty("serial")]
private long serial;
public long Serial
{
get
{
return serial;
}
set
{
if (serial != value)
{
serial = value;
RaisePropertyChanged("Serial");
}
}
}
[JsonProperty("formatType")]
private string formatType;
public string FormatType
{
get
{
return formatType;
}
set
{
if (formatType != value)
{
formatType = value;
RaisePropertyChanged("FormatType");
}
}
}
[JsonProperty("modifiedIso8601")]
private string modifiedIso8601;
public string ModifiedIso8601
{
get
{
return modifiedIso8601;
}
set
{
if (modifiedIso8601 != value)
{
modifiedIso8601 = value;
RaisePropertyChanged("ModifiedIso8601");
}
}
}
[JsonProperty("modifiedTimestamp")]
private long modifiedTimestamp;
public long ModifiedTimestamp
{
get
{
return modifiedTimestamp;
}
set
{
if (modifiedTimestamp != value)
{
modifiedTimestamp = value;
RaisePropertyChanged("ModifiedTimestamp");
}
}
}
[JsonProperty("timezone")]
private string timezone;
public string Timezone
{
get
{
return timezone;
}
set
{
if (timezone != value)
{
timezone = value;
RaisePropertyChanged("Timezone");
}
}
}
[JsonProperty("dataType")]
private string dataType;
public string DataType
{
get
{
return dataType;
}
set
{
if (dataType != value)
{
dataType = value;
RaisePropertyChanged("DataType");
}
}
}
[JsonProperty("exports")]
private ObservableCollection<SocialExportData> exports;
public ObservableCollection<SocialExportData> Exports
{
get
{
return exports;
}
set
{
if (exports != value)
{
exports = value;
RaisePropertyChanged("Exports");
}
}
}
//Event handling
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
//Console.WriteLine("Updated");
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}

在另一个类中,我有一个方法可以反序列化为我的 JSON 类的全局实例。它看起来像这样:

public SocialExportJSON socialExportData;
private async void DownloadAndDeserializeJSONAsync()
{
try
{
//Create a web client with the supplied credentials
var exportClient = new WebClient { Credentials = new NetworkCredential(uName, pw), Encoding = Encoding.UTF8};
//Create a task to download the JSON string and wait for it to finish
var downloadTask = Task.Run(() => exportClient.DownloadString(new Uri(eURL)));
downloadTask.Wait();
//Get the string from the task
var JSONString = await downloadTask;
//Create a task to deserialize the JSON from the last task
var DeserializeTask = Task.Run(() => JsonConvert.DeserializeObject<SocialExportJSON>(JSONString));
DeserializeTask.Wait();
SocialExportJSON sej = await DeserializeTask;
//Check the timestamp first to see if we should change the data
if(socialExportData == null)
{
//Get the data from the task
socialExportData = await DeserializeTask;
}
else if(sej.ModifiedTimestamp != socialExportData.ModifiedTimestamp)
{
//Get the data from the task
SocialExportJSON newData = await DeserializeTask;
GetNewItems(newData);
SetNewData(newData);
//Call the exportUpdated event when the task has finished
exportUpdated();
}
}
catch (Exception e)
{
MessageBox.Show(e.Message.ToString());
}
}

在我的 SetNewData 函数中(如下所示),我使用反射来设置全局类的属性。由于我要设置整个集合,而不是循环访问每个类中的每个属性,因此无法使用 CollectionChanged 事件来查找新项。

public void SetNewData(SocialExportJSON newData)
{
//Loop through each of the properties and copy from source to target
foreach (PropertyInfo pi in socialExportData.GetType().GetProperties())
{
if (pi.CanWrite)
{
pi.SetValue(socialExportData, pi.GetValue(newData, null), null);
}
}
}

有没有办法修改我的 SetNewData 函数,使其调用 CollectionChanged?如果没有,将任何新添加到我的 Item2 集合中的最佳方法是什么?

在我的主函数中。我创建了一个名为 SocialExport 的类实例,如下所示:

SocialExport s = new SocialExport("http://example.json", "example", "example");. 

这个类是包含我的 JSON 类的全局实例的地方,我的事件处理程序是这样添加

s.socialExportData.Exports[0].Items.CollectionChanged += CollectionChanged;

然后,您将为该特定实例CollectionChanged事件挂接一个事件处理程序ObservableCollection<Item2>

如果你创建一个新的ObservableCollection<Item2>,显然你也必须将事件处理程序挂接到这个。将新项添加到新实例时,不会调用与旧对象关联的事件处理程序。

因此,无论是否使用反序列化,无论是否创建新ObservableCollection<Item2>,都应挂接新的事件处理程序。

您可能可以在DownloadAndDeserializeJSONAsync方法中执行此操作。另一种选择是仅创建集合的一个实例,并从该实例中删除和添加项。

最新更新