2013-02-19 66 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); 
    } 
}