2

我有一个强类型对象列表。说List<Activity>。每个Activity都有许多属性,比如Title, Id, ParentActivity, ChildrenActivities,ActivityType等。列表是分层的,也就是说,列表中的每个活动都可能有子活动,每个子活动可能仍然有自己的子活动,等等。

我需要将此列表转换为 JSON,以便可以将其与第三方 JavaScript UI 库一起使用。但是,目标列表只有原始列表的一部分属性,例如IdTitle

因为我有许多类型和许多具有相同条件的地方,所以我不想定义目标列表类型,因此我没有强类型的目标。换句话说,我没有也List<SubActivity>不想创建这个SubActivity类。

如何即时进行这种分层转换,然后从目标列表中获取 JSON 字符串?是否有可能使用dynamic关键字、匿名类型

更新:

想象一下Activity

public class Activity
{
    public int Id { get; set; }

    public ActivityType Type { get; set; }

    public string ActivityTitle { get; set; }

    public string Description { get; set; }

    public Activity? Parent { get; set; }

    public List<Activity> Children { get; set; }
}

我有这个类实例的分层列表:

List<Activity> activities = ActivityManager.GetActivitiesHierarchically();

现在,我需要将此分层列表转换为 JSON 字符串,但我不需要呈现某些属性,包括Description例如。因此,在将列表序列化为 JSON 之前,我需要进行投影(某种转换)。我可能会创建一个名为的类型JsonActivity,如下所示:

public class JsonActivity
{
    public int id { get; set; }

    public string title { get; set; }

    public List<JsonActivity> items { get; set; }
}

但是因为这种模式在我的代码的许多地方针对不同类型重复,所以我不想定义JsonEntityDTO。

有没有办法通过动态投影进行分层转换?

4

1 回答 1

2

我认为你不能在 C# 中创建递归匿名类型,所以尝试使用它们是行不通的。

但是由于您要将结果序列化为 JSON,因此Dictionary<string, object>应该可以使用。

不过,lambda 必须是递归的。为了解决这个问题,您可以编写一个将自身作为参数的 lambda:

delegate IDictionary<string, object> RecursiveSelector<TSource>(
    RecursiveSelector<TSource> selector, TSource source);

static IEnumerable<IDictionary<string, object>> RecursiveSelect<TSource>(
    this IEnumerable<TSource> source,
    RecursiveSelector<TSource> selector)
{
    return source.Select(x => selector(selector, x));
}

然后你可以像这样使用它:

List<Activity> activities = …;
var result = activities.RecursiveSelect(
    (s, a) =>
    new Dictionary<string, object>
    { 
        { "id", a.Id },
        { "title", a.ActivityTitle },
        { "children", a.Children.Select(c => s(s, c)).ToArray() }
    });
于 2012-05-08T12:16:48.300 回答