2012-05-07 24 views
6

Đây là mã của tôi:Chuyển đổi năng động để phản đối

MyClass here = new MyClass(); 
IEnumerable<MyClass> vats = (IEnumerable<MyClass>)here.All(); 

Phương pháp Tất cả() trả về IEnumerable < động>. Tôi muốn chuyển nó sang IEnumerable < MyClass>. Dòng trên không làm việc, nó nói Không thể bỏ đối tượng thuộc loại 'd__15' để gõ 'System.Collections.Generic.IEnumerable`1 [MyClass]'.

Tôi cũng đã cố gắng:

IEnumerable<MyClass> vats = here.All() as IEnumerable<MyClass>; 

nhưng nó sẽ trả về null.

+0

Cách thức Tất cả() được triển khai? – Tigran

+0

@Tigran Đây rồi. Nhìn vào tập tin Massive.cs. https://github.com/robconery/massive –

+0

Bất kỳ lý do nào bạn không thể giữ nó "động" trong mã của mình? –

Trả lời

6

Tương tự như câu trả lời dbaseman (và comment AKX của) Tôi muốn sử dụng Cast:

IEnumerable<MyClass> vats = here.All().Cast<MyClass>(); 

Bạn sẽ cần một chỉ thị using cho LINQ mặc dù:

using System.Linq; 

ở đầu tệp của bạn. Có vẻ như bạn chưa hiểu điều đó nếu phương pháp Select không được nhận dạng.

Lưu ý rằng điều này giả định rằng mỗi giá trị thực sự là là tham chiếu MyClass.

EDIT: Nếu bạn muốn để có thể truy cập vào các giá trị của chỉ số, tôi khuyên bạn nên sử dụng ToList:

List<MyClass> vats = here.All().Cast<MyClass>().ToList(); 

Trong khi ToArray sẽ làm việc quá, cá nhân tôi ủng hộ danh sách trên mảng trong hầu hết trường hợp, như chúng khá linh hoạt hơn.

EDIT: Có vẻ như kết quả của bạn thực sự đầy ExpandoObject. Bạn sẽ cần tạo một phiên bản mới của MyClass từ mỗi mục, ví dụ:

List<MyClass> vats = here.All() 
         .Select(item => new MyClass(item.Name, item.Value)) 
         .ToList(); 

hoặc có thể là:

List<MyClass> vats = here.All() 
         .Select(item => new MyClass { 
            Name = item.Name, 
            Value = item.Value, 
           }) 
         .ToList(); 

Đó là chỉ một ví dụ, mà tôi sẽ không mong đợi để làm việc ngay lập tức - chúng tôi không thể làm bất kỳ tốt hơn khi chúng ta không biết gì về cách kết quả của bạn thực sự đang được trả lại.

Nghe có vẻ như bạn đang ở trên đầu của bạn ở đây, tôi sợ.

+0

Và nơi để tìm giá trị của tôi? [0], thùng [1]. Để kết quả ở đây.Tất cả() tôi có thể truy cập các giá trị như vậy –

+0

@srcee nếu bạn muốn có một người lập chỉ mục (thay vì lặp lại toàn bộ danh sách), bạn cần phải appen .ToArray() sau khi gọi để chọn –

+0

@ Srcee: Bạn có thể * lặp * qua các giá trị của bạn chỉ từ một chuỗi, nhưng nếu bạn muốn một người lập chỉ mục bạn sẽ cần một danh sách hoặc một mảng. Nhưng có vẻ như bạn khá mới đối với C# và LINQ - trong trường hợp đó tôi sẽ đề nghị bạn tránh xa việc gõ động trong một thời gian nếu bạn có thể ... nó sẽ làm cho việc hiểu những điều cơ bản khó hơn ... –

1

Bạn chỉ phải bỏ từng đối tượng cá nhân:

MyClass[] vats = here.All().Select(item => (MyClass)(dynamic)item).ToArray(); 
+1

'here.Cast ()' cũng sẽ hoạt động. – AKX

+0

@dbaseman Tôi nhận được lỗi trình biên dịch: không có phương thức Chọn nào. –

+0

@Scree đã chỉnh sửa. Xin lỗi về điều đó, đã đọc sai câu hỏi của bạn. – McGarnagle

0

Điều đầu tiên cần làm trước khi bạn có thể tạo giải pháp là loại đối tượng sẽ có trong thời gian chạy. Nhìn từ ý kiến ​​của bạn rằng họ sẽ được ExpandoObjects và giả sử MyClass không lấy được từ ExpandoObject bạn không thể sử dụng phương pháp .Cast<T> vì nó chỉ hỗ trợ phôi chứ không phải chuyển đổi tùy chỉnh.

Có một thủ thuật bạn có thể sử dụng để chuyển đổi từ ExpandoObjects sử dụng JavaScriptSerializer

lấy từ link này đây là một phương pháp mở rộng mà bạn có thể sử dụng

public static IEnumerable<T> Convert<T>(this IEnumerable<dynamic> self){ 
    var jsSerializer = new JavaScriptSerializer(); 
    foreach(var obj in self){ 
     yield return jsSerializer.ConvertToType<T>(obj); 
    } 
} 

trong trường hợp của bạn sau đó tất cả các bạn phải làm là thay đổi Cast in skeets trả lời thành Convert.

List<MyClass> vats = here.All().Convert<MyClass>().ToList(); 

Đây là một chút hackish vì JavaScriptSerializer không có nghĩa là làm điều này nhưng nó giải quyết được vấn đề.

Các vấn đề liên quan