Reputation: 51
How do I return an anonymous type which depends on the fields parameter in which properties which have to be included in anonymous type are listed? Task entity has more than 20 properties, and customers want to receive 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 });
}
}
Upvotes: 5
Views: 3881
Reputation: 51
In that case if Tasks is IQueryable<Task>
and we need to tighten from data source (for example, from a database) only those columns which are necessary for the client (not to overload the DB server), useful there is a SelectDynamic method. As a result the finished decision will be here such:
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;
}
}
A sample usage is here
Upvotes: 0
Reputation: 32581
You may try using the ExpandoObject
and 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 a sample usage is:
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);
}
}
Upvotes: 1
Reputation: 83
I hope it will help 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);
}
the view result:
[
[
{
"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"
}
]
]
Upvotes: 1