động không chứa định nghĩa cho thuộc tính từ tham chiếu dự án


93

Tôi gặp lỗi cho biết:

'object' không chứa định nghĩa cho 'Title'

tất cả mã cũng có 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ừ dự án SAME, nhưng nếu tôi thêm ConsoleApplication2 với tham chiếu đến ConsoleApplication1 và thêm mã Exact giống nhau

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 gặp lỗi:

'object' không chứa định nghĩa cho 'Title' **

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

  • o.Title 'o.Title' đã đưa ra một ngoại lệ của loại 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' dynamic {Microsoft.CSharp.RuntimeBinder.RuntimeBinderException}

Đây là ảnh chụp màn hình: nhập mô tả hình ảnh ở đây

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


Câu trả lời:


79

Bạn cần sử dụng ExpandoObject

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

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

28
Ông đã trải qua rất nhiều khó khăn để viết một câu hỏi phức tạp, nó sẽ được tốt đẹp để có để cho anh ta biết lý do tại sao anh ấy nhận được lỗi, như Robert gợi ý
Luis Ferrao

2
Có vẻ như bạn không thể sử dụng chức năng trình khởi tạo nội tuyến với đối tượng expando?
Roberto Bonini

1
Nên sử dụng ExpandoObject ở đâu? để tạo một đối tượng động hay để phân tích cú pháp một đối tượng động?
Hosein Aqajani 29/09/17

Tôi đã phải tìm kiếm thêm thông tin vì câu trả lời của Robert rất hữu ích nhưng tôi cần hiểu sâu hơn. Oreilly đã có một bài viết tốt trên các loại động ở đây: oreilly.com/learning/building-c-objects-dynamically
Billy Willoughby

139

Câu trả lời của Jahamal không nói lên lý do tại sao bạn lại mắc lỗi. Lý do là lớp ẩn danh là internalhợp ngữ. Từ khóa dynamickhô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 tên.

Đây là một ví dụ điển hình khác giải thích lý do và một giải pháp khả thi khác .

Lý do cuộc gọi data2.Personkhông thành công là thông tin loại data2không có sẵn trong thời gian chạy. Lý do nó không khả dụng là vì các loại ẩn danh không công khai. Khi phương thức trả về một thể hiện của kiểu ẩn danh đó, nó sẽ trả về một System.Object tham chiếu đến một thể hiện của kiểu ẩn danh - một kiểu có thông tin không có sẵn cho chương trình chính. Thời gian chạy động cố gắng tìm một thuộc tính được gọi Persontrên đối tượng, nhưng không thể giải quyết nó từ thông tin loại mà nó có. Như vậy, nó ném ra một ngoại lệ. Lời kêu gọi data.Namehoạt động tốt vì Personlà một lớp công khai, thông tin đó có sẵn và có thể dễ dàng giải quyết.

Điều này có thể ảnh hưởng đến bạn trong bất kỳ trường hợp nào sau đây (nếu không nhiều hơn):

  1. Bạn đang trả về một loại không công khai, không nội bộ bằng cách sử dụng System.Object. 2. Bạn đang trả về một kiểu dẫn xuất không công khai, không nội bộ thông qua kiểu cơ sở công khai và truy cập một thuộc tính trong kiểu dẫn xuất không có trong kiểu cơ sở. 3. Bạn đang trả lại bất cứ thứ gì được bao bọc bên trong một kiểu ẩn danh từ một hội đồng khác.

1
Bạn có thể trích dẫn nguồn của bạn trong câu trả lời của bạn được không?
d3dave

@ d3dave Có thể kiểm tra hai yêu cầu trong câu trả lời. Khả năng hiển thị của lớp có thể được kiểm tra trong trình dịch ngược .NET. Các quy tắc truy cập cho dynamiccó 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.
Robert Važan

3
Đây là câu trả lời thực sự cho việc tại sao những gì OP đang làm là một vấn đề.
Matti Virkkunen

1
Tôi không thể làm cho điều này hoạt động giữa nguồn và dự án thử nghiệm đều là netcoreapp1.1. Bất kỳ ý tưởng nếu đó chỉ là lỗi của tôi hoặc nếu điều này không hoạt động trong .NET Core?
Anthony Mastrean

29

Trong trường hợp của tôi, tôi có một dự án Unit Test mà tôi đã tạo trên Visual Studio và rất nhiều trường hợp tôi cần kiểm tra 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ả chúng nên tôi đã đánh dấu nhóm thử nghiệm là bạn bằng cách sử dụng:

[assembly:InternalsVisibleTo("MyDataLayerAssemblyName")]

Và điều đó đã giải quyết được nó.

Thí dụ:

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

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

   [TestClass]
   public class ContactTests
   {
      ...

Người giới thiệu:


1
Lý do là những gì Alexander Stepaniuk nói. Bình luận của bạn là giải pháp. Cảm ơn!
Pato Loco

Tôi không thể làm cho điều này hoạt động giữa các dự án netcoreapp1.1, không chắc liệu đó có phải là điều tôi đang làm không chính xác hay không.
Anthony Mastrean

Cảm ơn rất nhiều Jelgab! Bây giờ tôi không phải thay thế động bằng ExpanoObject! Tôi đang sử dụng tính năng tiêm phụ thuộc trong các bài kiểm tra đơn vị của mình và tôi không thể sử dụng động cũng như để nó hoạt động từ dự án kiểm tra đơn vị. Nhưng điều này đã giải quyết nó!
ShameWare

Lưu ý rằng bạn (nhà phát triển) phải thêm điều này vào dự án đối diện mà từ đó các loại ẩn danh đang được tạo hoặc cả hai, nếu đúng như vậy.
ryanwebjackson

0

Trong trường hợp của tôi, tôi có một dự án thử nghiệm xUnit.

Trong đó 'nội dung' là một chuỗi json .

Mã này gây ra lỗi:

dynamic parsed = JsonConvert.DeserializeObject<dynamic>(content);

Mã này hoạt động. Sử dụng ExpandoObject chèn thêm động như thế này:

dynamic parsed = JsonConvert.DeserializeObject<ExpandoObject>(content);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.