How to return a custom anonymous type?

How to return an anonymous type, which depends on the fields parameter, which lists the properties that should be included in the anonymous type? The Task object has more than 20 properties, and clients want different combinations of properties.

public class Test
{
    public class Task
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        //... more 20 properties
    }

    public List<Task> Tasks = new List<Task>();

    public Test()
    {
        Tasks.Add(new Task { Id = 1, Name = "Task #1", Description = "Description task #1" });
        Tasks.Add(new Task { Id = 2, Name = "Task #2", Description = "Description task #2" });
        Tasks.Add(new Task { Id = 3, Name = "Task #3", Description = "Description task #3" });
    }

    public IEnumerable<object> GetAllTasks(string fields)
    {
        //if fields == 'Id,Name' then return anonymous type new { Id = t.Id, Name = t.Name }
        return Tasks.Select(t => new { Id = t.Id, Name = t.Name });

        //if fields == 'Id,Name,Description' then return anonymous type new { Id = t.Id, name = t.Name, Description = t.Description }
        return Tasks.Select(t => new { Id = t.Id, Name = t.Name, Description = t.Description });
    }
}
+5
source share
3 answers

In this case, if Tasks IQueryable<Task>, and we need to pull from the data source (for example, from the database) only those columns that are necessary for the client (not to overload the database server), SelectDynamic is useful . As a result, the final solution will be as follows:

public class Test
{
    public class Task
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        //... more 20 properties
    }

    public IQueryable<Task> Tasks;

    public Test()
    {
        Tasks = new List<Task>
            {
                new Task {Id = 1, Name = "Task #1", Description = "Description task #1"},
                new Task {Id = 2, Name = "Task #2", Description = "Description task #2"},
                new Task {Id = 3, Name = "Task #3", Description = "Description task #3"}
            }.AsQueryable();
    }

    public IEnumerable<object> GetAllTasks(string[] fields)
    {
        var response = new List<object>();
        var customTasks = Tasks.SelectDynamic(fields).Cast<dynamic>();
        foreach (var t in customTasks.Take(100))
        {
            dynamic expando = new ExpandoObject();

            if (fields.Contains("Id")) expando.Id = t.Id;
            if (fields.Contains("Name")) expando.Name = t.Name;
            if (fields.Contains("Description")) expando.Description = t.Description;
            // ... other properties

            response.Add(expando);
        }
        return response;
    }
}

Usage example here

0
source

I hope this helps you

public List<Task> Tasks = new List<Task>();

public void Test()
{
    Tasks.Add(new Task { Id = 1, Name = "Task #1", Description = "Description task #1" });
    Tasks.Add(new Task { Id = 2, Name = "Task #2", Description = "Description task #2" });
    Tasks.Add(new Task { Id = 3, Name = "Task #3", Description = "Description task #3" });
}

public ActionResult Index()
{
    Test();

    return Json(GetAllTasks(), JsonRequestBehavior.AllowGet);
}

public IEnumerable<object> GetAllTasks()
{
    return Tasks.Select(GetTask);
}

private object GetTask(Task task)
{
    dynamic expandoObject = new ExpandoObject();
    //your if statment block
    if (task.Id == 1)
    {
        expandoObject.Id = task.Id;
    }

    expandoObject.Name = task.Name;
    expandoObject.Description = task.Description;

    var dictionary = expandoObject as IDictionary<string, object>;
    return dictionary.ToDictionary(item => item.Key, item => item.Value);
}

:

[
   [
      {
         "Key":"Id",
         "Value":1
      },
      {
         "Key":"Name",
         "Value":"Task #1"
      },
      {
         "Key":"Description",
         "Value":"Description task #1"
      }
   ],
   [
      {
         "Key":"Name",
         "Value":"Task #2"
      },
      {
         "Key":"Description",
         "Value":"Description task #2"
      }
   ],
   [
      {
         "Key":"Name",
         "Value":"Task #3"
      },
      {
         "Key":"Description",
         "Value":"Description task #3"
      }
   ]
]
+1

You can try using ExpandoObjectand System.Reflection:

public IEnumerable<object> GetAllTasks(string[] fields)
{
    List<object> response = new List<object>();
    Tasks.ForEach((a) =>
    {
        dynamic expando = new ExpandoObject();
        var p = expando as IDictionary<String, object>;
        foreach (string item in fields)
        {
            p[item] = a.GetType().GetProperty(item).GetValue(a);
        }
        response.Add(expando);
    });
    return response;
}

And an example of use:

static void Main(string[] args)
{
    var test = new Test();
    var results = test.GetAllTasks(new[] { "Id"});
    foreach (var result in results)
    {
        Console.WriteLine((result as dynamic).Id);
    }

    results = test.GetAllTasks(new[] { "Name", "Description" });
    foreach (var result in results)
    {
        var dynamicResult=result as dynamic;
        Console.WriteLine("{0} {1}", dynamicResult.Name, dynamicResult.Description);
        // The following line will throw an exception
        //Console.WriteLine((result as dynamic).Id);
    }
}
+1
source

All Articles