dinamik, bir proje referansındaki bir özellik için bir tanım içermez


93

Şöyle bir hata alıyorum:

"nesne", "Başlık" için bir tanım içermiyor

tüm kod da github'da

Buna benzeyen bir ConsoleApplication1 kullanıyorum

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

ve Movie.cs

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

SAME projesinden sorunsuz çalışıyor, ancak ConsoleApplication2'yi ConsoleApplication1 referansıyla eklersem ve Tam olarak aynı kodu eklersem

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

Bir hata alıyorum:

"nesne", "Başlık" için bir tanım içermiyor **

dinamik nesnede olmasına rağmen.

  • o.Title 'o.Title', 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' türünde bir istisna attı dinamik {Microsoft.CSharp.RuntimeBinder.RuntimeBinderException}

İşte bir ekran görüntüsü: görüntü açıklamasını buraya girin

Bunun gibi bir şey yapıyorum ve bir test projesinden film işlevini çağırmaya çalışıyorum.


Yanıtlar:


79

Bir ExpandoObject kullanmanız gerekiyor

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

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

28
Ayrıntılı bir soru yazmak için çok fazla zahmete girdi, Robert'ın önerdiği gibi neden hatayı aldığını ona bildirmek güzel olurdu
Luis Ferrao

2
Satır içi başlatıcı işlevini expando nesnesiyle kullanabilecek gibi görünmüyor mu?
Roberto Bonini

1
ExpandoObject nerede kullanılmalıdır? dinamik bir nesne oluşturmak için mi yoksa dinamik bir nesneyi ayrıştırmak için mi?
Hosein Aqajani

Robert'ın cevabı yardımcı olduğu için daha fazla bilgi aramak zorunda kaldım, ancak daha derin bir anlayışa ihtiyacım vardı. Oreilly'nin
Billy Willoughby

139

Jahamal'ın cevabı neden hatayı aldığınızı söylemiyor . Bunun nedeni, anonim sınıfın internalmecliste olmasıdır. Anahtar kelime dynamic, üye görünürlüğünü atlamanıza izin vermez.

Çözüm, anonim sınıfı adlandırılmış genel sınıfla değiştirmektir.

İşte sebebini ve olası başka bir çözümü açıklayan başka bir güzel örnek .

Çağrının data2.Personbaşarısız olmasının nedeni, türünün data2çalışma zamanında mevcut olmamasıdır. Mevcut olmamasının nedeni, anonim türlerin herkese açık olmamasıdır. Yöntem, bu anonim türün bir örneğini döndürdüğünde, anonim türün System.Objecbir örneğine başvuran bir t döndürür - bilgileri ana programda mevcut olmayan bir tür. Dinamik çalışma zamanı Person, nesnede çağrılan bir özelliği bulmaya çalışır , ancak bunu sahip olduğu tür bilgilerinden çözemez. Bu nedenle, bir istisna atar. Herkese açık bir sınıf olduğundan, bu bilgiler mevcut olduğundan ve kolayca çözülebildiğinden, çağrı data.Nameiyi çalışıyor Person.

Bu sizi aşağıdaki durumlardan herhangi birinde etkileyebilir (daha fazla değilse):

  1. Kullanarak halka açık olmayan, dahili olmayan bir türü iade ediyorsunuz System.Object. 2. Herkese açık olmayan, dahili olmayan türetilmiş bir türü bir genel temel tür aracılığıyla döndürüyorsunuz ve temel türde olmayan türetilmiş türdeki bir özelliğe erişiyorsunuz. 3. Farklı bir derlemeden anonim bir türe sarılmış her şeyi iade ediyorsunuz.

1
Cevabınızda kaynağınızı belirtir misiniz lütfen?
d3dave

@ d3dave Yanıttaki iki iddia test edilebilir. Sınıf görünürlüğü .NET decompiler'da kontrol edilebilir. Erişim kuralları dynamic, farklı görünürlükteki üyelerle bir test sınıfında kontrol edilebilir.
Robert Važan

3
OP'nin yaptığı şeyin neden bir sorun olduğuna dair gerçek cevap budur.
Matti Virkkunen

1
Bunun, her ikisi de netcoreapp1.1 olan bir kaynak ve test projesi arasında çalışmasını sağlayamıyorum. Bunun benim hatam olup olmadığı veya .NET Core'da çalışmadığına dair bir fikriniz var mı?
Anthony Mastrean

29

Benim durumumda, Visual Studio üzerinde oluşturduğum bir Birim Testi projem ve bir veri katmanı kitaplığındaki yöntemleri test etmem gereken birçok durum vardı. Hepsini değiştirmek istemedim, bu yüzden test montajını şunu kullanarak bir arkadaş olarak işaretledim:

[assembly:InternalsVisibleTo("MyDataLayerAssemblyName")]

Ve bu onu çözdü.

Misal:

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

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

   [TestClass]
   public class ContactTests
   {
      ...

Referanslar:


1
Nedeni, Alexander Stepaniuk'un söylediği şey. Yorumunuz çözümdür. Teşekkürler!
Pato Loco

Bunu netcoreapp1.1 projeleri arasında çalıştıramıyorum, yanlış yaptığım bir şey olup olmadığından emin değilim.
Anthony Mastrean

Büyük Teşekkürler Jelgab! Artık dynamic'i ExpanoObject ile değiştirmeme gerek yok! Birim testlerimde bağımlılık enjeksiyonu kullanıyorum ve dinamik kullanamadım ve birim test projesinden çalışmasını sağladım. Ama bu sorunu çözdü!
ShameWare

Siz (geliştirici) bunu anonim türlerin oluşturulduğu zıt projeye veya durum buysa her ikisine de eklemeniz gerektiğini unutmayın.
ryanwebjackson

0

Benim durumumda bir xUnit test projem var.

Burada 'içerik' bir json dizesidir .

Bu kod hata verir:

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

Bu kod çalışır. ExpandoObject örneğini dinamik olarak şu şekilde kullanın :

dynamic parsed = JsonConvert.DeserializeObject<ExpandoObject>(content);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.