2012-02-23 43 views
59

Tôi nhận được một lỗi mà nói:động không chứa một định nghĩa cho một tài sản từ một tài liệu tham khảo dự án

'object' does not contain a definition for 'Title'

tất cả các mã cũng là trên github

Tôi có một ConsoleApplication1 trông như thế này

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Movie m = new Movie(); 
      var o = new { Title = "Ghostbusters", Rating = "PG" }; 
      Console.WriteLine(m.PrintMovie(o)); 
     } 
    } 
} 

Movie.cs

public class Movie : DynamicObject 
{ 
    public string PrintMovie(dynamic o) 
    { 
     return string.Format("Title={0} Rating={1}", o.Title, o.Rating); 
    } 
} 

nó hoạt động tốt từ các dự án tương tự, nhưng nếu tôi thêm ConsoleApplication2 với một tham chiếu đến ConsoleApplication1 và thêm cùng một mã chính xác

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Movie m = new Movie(); 
      var o = new { Title = "Ghostbusters", Rating = "PG" }; 
      Console.WriteLine(m.PrintMovie(o)); 
     } 
    } 
} 

tôi nhận được một lỗi:

'object' does not contain a definition for 'Title'**

mặc dù nó nằm trong đối tượng động.

  • o.Title 'o.Title' ném một ngoại lệ của loại 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' động {} Microsoft.CSharp.RuntimeBinder.RuntimeBinderException

Đây là một ảnh chụp màn hình: enter image description here

Tôi đang làm điều gì đó như thế này và cố gắng gọi hàm phim từ dự án thử nghiệm.

+1

thể trùng lặp của [C# 'năng động' không thể truy cập các thuộc tính từ các kiểu nặc danh tuyên bố trong lắp ráp khác] (http: // stackoverflow .com/questions/2630370/c-sharp-dynamic-cannot-access-properties-from-anonymous-types-khai báo-in-anot) –

Trả lời

61

Bạn cần phải sử dụng một ExpandoObject

dynamic o = new ExpandoObject(); 
o.Title = "Ghostbusters"; 
o.Rating = "PG"; 

Console.WriteLine(m.PrintMovie(o)); 
+13

Ông đã trải qua rất nhiều rắc rối để viết một chuỗi phức tạp stion, nó sẽ được tốt đẹp để cho anh ta biết lý do tại sao anh ta nhận được lỗi, như Robert gợi ý –

+0

Dường như bạn có thể sử dụng chức năng khởi tạo nội tuyến với đối tượng expando? –

+0

Tuyệt vời, Nó cũng hoạt động với thử nghiệm Đơn vị –

90

câu trả lời Jahamal của không nói lý do tại sao bạn nhận được lỗi. Lý do là lớp vô danh là internal để lắp ráp. Từ khóa dynamic không cho phép bạn bỏ qua khả năng hiển thị của thành viên.

Giải pháp là thay thế lớp ẩn danh bằng lớp công khai có tên.

Dưới đây là một ví dụ khác giải thích lý do và another possible solution.

The reason the call to data2.Person fails is that the type information of data2 is not available at runtime. The reason it's not available is because anonymous types are not public. When the method is returning an instance of that anonymous type, it's returning a System.Objec t which references an instance of an anonymous type - a type who's info isn't available to the main program. The dynamic runtime tries to find a property called Person on the object, but can't resolve it from the type information it has. As such, it throws an exception. The call to data.Name works fine since Person is a public class, that information is available and can be easily resolved.

This can affect you in any of the following cases (if not more):

  1. You're returning a non-public, non-internal type using System.Object .
  2. You're returning a non-public, non-internal derived type via a public base type and accessing a property in the derived type that's not in the base type.
  3. You're returning anything wrapped inside an anonymous type from a different assembly.
+0

Bạn có thể trích dẫn nguồn của mình trong câu trả lời không? – d3dave

+0

@ d3dave Hai xác nhận quyền sở hữu trong câu trả lời có thể được kiểm tra. Khả năng hiển thị lớp có thể được kiểm tra trong trình giải mã .NET. Các quy tắc truy cập cho 'dynamic' có thể được kiểm tra trên một lớp thử nghiệm với các thành viên có khả năng hiển thị khác nhau. –

+1

Đây là câu trả lời thực sự cho lý do tại sao những gì OP đã làm là một vấn đề. –

15

Trong trường hợp của tôi, tôi đã có dự án Thử nghiệm đơn vị mà tôi đã tạo trên Visual Studio và rất nhiều trường hợp tôi cần thử nghiệm các phương pháp trên thư viện lớp dữ liệu. Tôi không muốn thay đổi tất cả trong số họ vì vậy tôi đánh dấu sự lắp ráp thử nghiệm như một người bạn bằng cách sử dụng:

[assembly: InternalsVisibleTo ("MyDataLayerAssemblyName")]

Và đó giải quyết nó.

Ví dụ:

using System.Runtime.CompilerServices; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 

[assembly: InternalsVisibleTo("MyDataLayerAssembly")] 
namespace MyUnitTestProject.DataTests 
{ 

    [TestClass] 
    public class ContactTests 
    { 
     ... 

Tài liệu tham khảo: InternalsVisibleToAttribute Class

Friend Assemblies

+1

Lý do là những gì Alexander Stepaniuk nói. Nhận xét của bạn là giải pháp. Cảm ơn! –

+0

Tôi không thể làm điều này để làm việc giữa các dự án netcoreapp1.1, không chắc chắn nếu nó là một cái gì đó tôi đang làm không chính xác. –

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