ไดนามิกไม่มีคำจำกัดความสำหรับคุณสมบัติจากการอ้างอิงโครงการ


93

ฉันได้รับข้อผิดพลาดที่แจ้งว่า:

'object' ไม่มีคำจำกัดความสำหรับ 'Title'

โค้ดทั้งหมดยังอยู่ในgithub

ฉันมี ConsoleApplication1 ที่มีลักษณะเช่นนี้

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

มันใช้งานได้ดีจากโปรเจ็กต์ SAME แต่ถ้าฉันเพิ่ม ConsoleApplication2 ด้วยการอ้างอิงถึง ConsoleApplication1 และเพิ่มรหัสเดียวกันแน่นอน

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

ฉันได้รับข้อผิดพลาด:

'object' ไม่มีคำจำกัดความสำหรับ 'Title' **

แม้ว่าจะอยู่ในวัตถุไดนามิก

  • o.Title 'o.Title' มีข้อยกเว้นประเภท 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' ไดนามิก {Microsoft.CSharp.RuntimeBinder.RuntimeBinderException}

นี่คือภาพหน้าจอ: ป้อนคำอธิบายภาพที่นี่

ฉันกำลังทำอะไรแบบนี้และพยายามเรียกใช้ฟังก์ชันภาพยนตร์จากโปรเจ็กต์ทดสอบ


คำตอบ:


79

คุณต้องใช้ ExpandoObject

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

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

28
เขาเดินผ่านจำนวนมากของปัญหาที่จะเขียนเป็นคำถามที่ซับซ้อนก็จะดีที่จะมีให้เขารู้ว่าทำไมเขาถึงได้รับข้อผิดพลาดในขณะที่โรเบิร์ตแสดงให้เห็น
หลุยส์ Ferrao

2
ดูเหมือนคุณจะไม่สามารถใช้ฟังก์ชันการเริ่มต้นอินไลน์กับอ็อบเจกต์ expando ได้หรือไม่?
Roberto Bonini

1
ควรใช้ ExpandoObject ที่ไหน? สำหรับการสร้างวัตถุแบบไดนามิกหรือสำหรับการแยกวิเคราะห์วัตถุแบบไดนามิก?
Hosein Aqajani

ฉันต้องค้นหาข้อมูลเพิ่มเติมเนื่องจากคำตอบของโรเบิร์ตมีประโยชน์ แต่ฉันต้องการความเข้าใจที่ลึกซึ้งยิ่งขึ้น Oreilly มีบทความดีๆเกี่ยวกับประเภทไดนามิกที่นี่: oreilly.com/learning/building-c-objects-
Billy Willoughby

139

คำตอบของ Jahamal ไม่ได้บอกว่าทำไมคุณถึงได้รับข้อผิดพลาด เหตุผลก็คือคลาสที่ไม่ระบุชื่อคือinternalการชุมนุม คีย์เวิร์ดdynamicไม่อนุญาตให้คุณข้ามการมองเห็นของสมาชิก

วิธีแก้ไขคือแทนที่คลาสที่ไม่ระบุชื่อด้วยคลาสสาธารณะที่มีชื่อ

นี่คือตัวอย่างที่ดีอีกอธิบายเหตุผลและวิธีการแก้ปัญหาที่เป็นไปได้อีก

สาเหตุที่การโทรdata2.Personล้มเหลวคือข้อมูลประเภทdata2ไม่พร้อมใช้งานในรันไทม์ สาเหตุที่ไม่สามารถใช้งานได้เนื่องจากประเภทที่ไม่ระบุตัวตนไม่ใช่แบบสาธารณะ เมื่อเมธอดส่งคืนอินสแตนซ์ของประเภทที่ไม่ระบุตัวตนนั้นจะส่งคืนSystem.Object ที่อ้างอิงอินสแตนซ์ของประเภทที่ไม่ระบุตัวตนซึ่งเป็นประเภทที่ไม่มีข้อมูลในโปรแกรมหลัก ไดนามิกรันไทม์พยายามค้นหาคุณสมบัติที่เรียกPersonบนอ็อบเจ็กต์ แต่ไม่สามารถแก้ไขได้จากข้อมูลประเภทที่มี ดังนั้นจึงมีข้อยกเว้น การเรียกร้องให้data.Nameทำงานได้ดีเนื่องจากPersonเป็นชั้นสาธารณะข้อมูลนั้นพร้อมใช้งานและสามารถแก้ไขได้ง่าย

สิ่งนี้อาจส่งผลกระทบต่อคุณในกรณีใด ๆ ต่อไปนี้ (ถ้าไม่มากกว่านั้น):

  1. System.Objectคุณกำลังกลับไม่ใช่แบบสาธารณะไม่ใช่ประเภทภายในใช้ 2. คุณส่งคืนประเภทที่ได้รับที่ไม่เป็นสาธารณะและไม่ใช่ภายในผ่านประเภทฐานสาธารณะและเข้าถึงคุณสมบัติในประเภทที่ได้รับซึ่งไม่ได้อยู่ในประเภทฐาน 3. คุณกำลังส่งคืนสิ่งที่ห่ออยู่ในประเภทที่ไม่ระบุตัวตนจากชุดประกอบอื่น

1
คุณสามารถอ้างอิงแหล่งที่มาของคุณในคำตอบของคุณได้ไหม
d3dave

@ d3dave สามารถทดสอบข้อเรียกร้องสองข้อในคำตอบได้ การมองเห็นคลาสสามารถตรวจสอบได้ในตัวถอดรหัส. NET กฎการเข้าถึงdynamicสามารถตรวจสอบได้ในชั้นเรียนทดสอบที่มีสมาชิกที่มีการเปิดเผยที่แตกต่างกัน
Robert Važan

3
นี่คือคำตอบที่แท้จริงว่าเหตุใด OP จึงเป็นปัญหา
Matti Virkkunen

1
ฉันไม่สามารถใช้งานได้ระหว่างแหล่งที่มาและโครงการทดสอบที่เป็นทั้ง netcoreapp1.1 มีความคิดอย่างไรว่ามันเป็นเพียงความผิดของฉันหรือถ้าสิ่งนี้ใช้ไม่ได้ใน. NET Core?
Anthony Mastrean

29

ในกรณีของฉันฉันมีโครงการทดสอบหน่วยที่ฉันสร้างบน Visual Studio และมีหลายกรณีที่ฉันต้องทดสอบวิธีการในไลบรารีชั้นข้อมูล ฉันไม่ต้องการเปลี่ยนทั้งหมดดังนั้นฉันจึงทำเครื่องหมายชุดทดสอบเป็นเพื่อนโดยใช้:

[assembly:InternalsVisibleTo("MyDataLayerAssemblyName")]

และนั่นแก้ไขได้

ตัวอย่าง:

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

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

   [TestClass]
   public class ContactTests
   {
      ...

อ้างอิง:


1
เหตุผลคือสิ่งที่ Alexander Stepaniuk พูด ความคิดเห็นของคุณคือทางออก ขอบคุณ!
Pato Loco

ฉันไม่สามารถใช้งานระหว่างโปรเจ็กต์ netcoreapp1.1 ได้ไม่แน่ใจว่าเป็นสิ่งที่ฉันทำไม่ถูกต้องหรือไม่
Anthony Mastrean

ขอบคุณมาก Jelgab! ตอนนี้ฉันไม่ต้องแทนที่ไดนามิกด้วย ExpanoObject! ฉันใช้การฉีดพึ่งพาในการทดสอบหน่วยของฉันและฉันไม่สามารถใช้ไดนามิกและทำให้มันทำงานได้จากโครงการทดสอบหน่วย แต่สิ่งนี้แก้ไขได้!
ShameWare

โปรดทราบว่าคุณ (ผู้พัฒนา) ต้องเพิ่มสิ่งนี้ในโปรเจ็กต์ตรงข้ามที่กำลังสร้างชนิดที่ไม่ระบุตัวตนหรือทั้งสองอย่างหากเป็นกรณี
ryanwebjackson

0

ในกรณีของฉันฉันมีโครงการทดสอบ xUnit

ที่ไหน 'เนื้อหา' เป็นสตริง JSON

รหัสนี้แสดงข้อผิดพลาด:

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

รหัสนี้ใช้งานได้ ใช้ExpandoObject ที่สร้างขึ้นจากไดนามิกเช่นนี้:

dynamic parsed = JsonConvert.DeserializeObject<ExpandoObject>(content);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.