У меня есть класс, который немного похож на следующий
public class SpecialList<T> : List<T>
{
public SingleOrList() { }
public SingleOrList(IEnumerable<T> list) : base(list) {}
...
}
При преобразовании его из JSON он может быть превращен в этот специальный список либо как отдельный объект, либо как массив этого объект следующим образом.
...
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
var originalList = token.ToObject(objectType.BaseType, serializer);
return Activator.CreateInstance(objectType, originalList);
}
var list = (IList) Activator.CreateInstance(objectType);
var genericType = objectType.GetGenericArguments().Single();
var single = token.ToObject(genericType, serializer);
list.Add(single);
return list;
}
Игнорируя тот факт, является ли это хорошей идеей на данный момент, меня интересовало, можете ли вы использовать / как использовать здесь согласованные деревья выражений вместо Activator.CreateInstance
для создания классов.
В большинстве примеров, которые я видел, используются дженерики, которые для меня здесь невозможны, поскольку я не знаю заранее тип generi c, например
public static Func<T> Instance = Expression.Lambda<Func<T>>(Expression.New(typeof(T))).Compile();
На основе комментария canton7, где TypeCreators
- это некая форма кеша:
private static IList CreateForType(Type objectType)
{
if (TypeCreators.TryGetValue(objectType, out var func))
{
return func();
}
var newFunc = Expression.Lambda<Func<IList>>(Expression.New(objectType)).Compile();
TypeCreators.TryAdd(objectType, newFunc);
return newFunc();
}