C# 自己的SynchronizedCollection的Json.net序列化
我已经编写了一个非常基本的同步集合,用于桌面应用程序。有没有比这更好/更容易的方法?集合需要由json.net直接序列化,显然它需要同步 我还想知道是否可以强制转换为未知的泛型类型来调用copy函数generic,而无需强制转换到接口。我认为这在一个大的列表中可能非常缓慢,而且似乎没有必要C# 自己的SynchronizedCollection的Json.net序列化,c#,json.net,C#,Json.net,我已经编写了一个非常基本的同步集合,用于桌面应用程序。有没有比这更好/更容易的方法?集合需要由json.net直接序列化,显然它需要同步 我还想知道是否可以强制转换为未知的泛型类型来调用copy函数generic,而无需强制转换到接口。我认为这在一个大的列表中可能非常缓慢,而且似乎没有必要 public class SynchronizedCollectionConverter : JsonConverter { public override bool CanConvert(Type
public class SynchronizedCollectionConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(SynchronizedCollection<>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
// make list type from SynchronizedCollection generic type
var listType = typeof(List<>).MakeGenericType(objectType.GenericTypeArguments[0]);
// create instance of list type
var list = Activator.CreateInstance(listType);
// populate json to our list!
serializer.Populate(reader, list);
// create new SynchronizedCollection from populated list, easy! <3 json <3 c#
return Activator.CreateInstance(objectType, list);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
SynchronizedCollectionCopy collection = value as SynchronizedCollectionCopy;
// get a copy of the list synchronously
using (var waitTask = Task.Run<List<object>>(async () => { return await collection.Copy(); }))
{
// wait for synchronization.
waitTask.Wait();
// aaand serialize
serializer.Serialize(writer, waitTask.Result);
}
}
}
public interface SynchronizedCollectionCopy
{
Task<List<object>> Copy();
}
public class SynchronizedCollection<T> : IDisposable, SynchronizedCollectionCopy
{
private List<T> _storage;
private SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
public int Count { get { return _storage.Count; } }
public SynchronizedCollection()
{
_storage = new List<T>();
}
public SynchronizedCollection(IEnumerable<T> items)
{
_storage = new List<T>(items);
}
public async Task Add(T item)
{
await _lock.WaitAsync();
try
{
_storage.Add(item);
}
catch
{
throw;
}
finally
{
_lock.Release();
}
}
public async Task Remove(Func<T, bool> predicate)
{
await _lock.WaitAsync();
try
{
T item;
while ((item = _storage.FirstOrDefault(predicate)) != null)
{
_storage.Remove(item);
}
}
catch
{
throw;
}
finally
{
_lock.Release();
}
}
public async Task Perform(Action<List<T>> actionOnList)
{
await _lock.WaitAsync();
try
{
actionOnList(_storage);
}
catch
{
throw;
}
finally
{
_lock.Release();
}
}
public async Task<List<object>> Copy()
{
await _lock.WaitAsync();
List<object> list = null;
try
{
list = new List<object>(_storage.Cast<object>());
}
catch
{
throw;
}
finally
{
_lock.Release();
}
return list;
}
public void Dispose()
{
_lock.Dispose();
}
}
公共类SynchronizedCollectionConverter:JsonConverter
{
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType.IsGenericType&&objectType.GetGenericTypeDefinition()==typeof(SynchronizedCollection);
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
if(reader.TokenType==JsonToken.Null)
返回null;
//从SynchronizedCollection泛型类型生成列表类型
var listType=typeof(List).MakeGenericType(objectType.GenericTypeArguments[0]);
//创建列表类型的实例
var list=Activator.CreateInstance(listType);
//将json填充到我们的列表中!
序列化程序。填充(读取器、列表);
//从填充的列表中创建新的SynchronizedCollection,很简单!1)鉴于您的类没有实现ICollection
,这可能是最简单的。2)转换到接口应该花费很少的时间,比Json.NET完成的任何工作都要少。但是多次调用Activator.CreateInstance
可能需要一些时间。您是否已经对它进行了剖析?参见3)通过返回<代码>列表>代码>框值类型。考虑返回<代码> t[] /Cords>类型为<代码>系统。数组< /代码>并允许Json.NET推断元素类型。还考虑提供一个非异步版本的<代码>()/代码>以方便。4)在您的代码> Read jSar()中。
忽略传入的对象值
。您可能需要检查它是否非空,是否可以强制转换为同步集合
,如果是,则填充并返回它,而不是填充并返回新值。5)而不是分两步分配并填充列表
,只需在一步中使用。6)S由于您的代码有效,这个问题可能更适合Thx的建议!我完全忘记了SE上的codereview。对于第4点,在调用ReadJson时,在什么情况下可以设置对象值?我没有正确地表达我自己,转换到接口的速度很快,我知道,但将整个列表转换到列表,我甚至不需要知道WriteJson可能会很慢。在什么情况下调用ReadJson时可以设置对象值?-例如,当使用get only预分配集合反序列化到对象时,例如public class RootObject{readonly observeCollection collection=new observeableCollection();公共observeCollection集合{get{return Collection;}}}}