2013-02-19 55 views
5

如何返回一个匿名类型,该类型取决于必须包含在匿名类型中的属性所在的fields参数?任务实体拥有超过20个属性,并且客户希望接收不同的属性组合。如何返回自定义匿名类型?

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 }); 
    } 
} 
+3

匿名类型是在编译类型是已知的。你想在运行时动态构建类型。这是完全不同的。这也意味着'GetAllTask​​s'的消费者必须能够处理动态类型。除此之外,不建议返回匿名类型。 – 2013-02-19 08:52:17

+0

您已经定义了类Task,为什么不使用它而不是匿名类型? – 2013-02-19 08:52:52

+0

您可以使用反射尝试设置任务对象中传递的所有字段的值 – glosrob 2013-02-19 08:53:08

回答

0

在这种情况下,如果任务是IQueryable<Task>,我们需要从数据源收紧(例如,从数据库中)只有那些所必需的客户端(未超载DB服务器)列,有用的是有一个SelectDynamic方法。其结果是成品决定将在这里,例如:

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; 
    } 
} 

样品用法是here

1

我希望它会帮助你

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

你会考虑添加一些叙述来解释为什么这个代码作品,以及是什么使它成为这个问题的答案?这对询问问题的人以及任何其他人来说非常有帮助。 – 2013-02-20 10:52:45

1

您可以尝试使用ExpandoObjectSystem.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; 
} 

和样本用法是:

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); 
    } 
}