0

I have a method that uses MediaInfo.exe to get information from a video file and returns a dynamic object. When the code runs, the information is readable inside the method but when I return the dynamic object, it throws a RuntimeBinderException with this error:

CS0021: Cannot apply indexing with [] to an expression of type 'object'.

I call the method with:

dynamic o = GetMediaInfoJson(filename);

I type o["media"]["track"][1]["@type"] in the Immediate Window and get the error. Same error if I try to reference it with an "if" statement. ...

public dynamic GetMediaInfoJson(filename)
{
    string s = GetMediaInfoOutput(filename);  // s = json output from MediaInfo.exe
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    dynamic o = serializer.Deserialize<dynamic>(s);

    return o;

I type o["media"]["track"][1]["@type"] in the Immediate Window and seethe correct value.

I.e. after the return I "reference" o["media"]["track"][1]["@type"] and get the error! Why can I reference the dynamic variable inside the method but not when it's returned?

Using Visual Studio 2019 on Windows Service Server 2019. Error is run-time, not compile time error.

Attempt at Minimum Reproducible Example:

dynamic o = GetMediaInfo();


    public dynamic MediaInfoJson()
    {
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        string s = "{\"media\": {\"@ref\": \"d:\\\\inetpub\\\\ftproot\\\\slides\\\\1063_0_0_6_old.mp4\",\"track\": [{\"@type\": \"general\",\"videocount\": \"1\",\"audiocount\": \"1\",\"fileextension\": \"mp4\",\"format\": \"mpeg-4\",\"format_profile\": \"base media\",\"codecid\": \"isom\",\"codecid_compatible\": \"isom/iso2/avc1/mp41\",\"vidSize\": \"9199451\",\"vidSeconds\": \"31.834\",\"overallbitrate\": \"2311856\",\"vidFrameRate\": \"30.000\",\"framecount\": \"955\",\"streamsize\": \"26218\",\"headersize\": \"40\",\"datasize\": \"9173241\",\"footersize\": \"26170\",\"isstreamable\": \"no\",\"file_created_date\": \"utc 2021-05-24 21:04:22.909\",\"file_created_date_local\": \"2021-05-24 17:04:22.909\",\"file_modified_date\": \"utc 2021-05-24 21:04:22.914\",\"file_modified_date_local\": \"2021-05-24 17:04:22.914\",\"encoded_application\": \"lavf58.45.100\"},{\"@type\": \"video\",\"streamorder\": \"0\",\"id\": \"1\",\"format\": \"avc\",\"format_profile\": \"high\",\"format_level\": \"3\",\"format_settings_cabac\": \"yes\",\"format_settings_refframes\": \"4\",\"codecid\": \"avc1\",\"vidSeconds\": \"31.834\",\"bitrate\": \"2177206\",\"vidWidth\": \"790\",\"vidHeight\": \"402\",\"stored_vidWidth\": \"800\",\"stored_vidHeight\": \"416\",\"sampled_vidWidth\": \"790\",\"sampled_vidHeight\": \"402\",\"pixelaspectratio\": \"1.000\",\"vidAspect\": \"1.965\",\"vidRotation\": \"0.000\",\"vidFrameRate_mode\": \"cfr\",\"vidFrameRate_mode_original\": \"vfr\",\"vidFrameRate\": \"30.000\",\"framecount\": \"955\",\"colorspace\": \"yuv\",\"chromasubsampling\": \"4:2:0\",\"bitdepth\": \"8\",\"scantype\": \"progressive\",\"streamsize\": \"8663467\",\"encoded_library\": \"x264 - core 161\",\"encoded_library_name\": \"x264\",\"encoded_library_version\": \"core 161\",\"encoded_library_settings\": \"cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=3 / lookahead_threads=1 / sliced_threads = 0 / nr = 0 / decimate = 1 / interlaced = 0 / bluray_compat = 0 / constrained_intra = 0 / bframes = 3 / b_pyramid = 2 / b_adapt = 1 / b_bias = 0 / direct = 1 / weightb = 1 / open_gop = 0 / weightp = 2 / keyint = 250 / keyint_min = 25 / scenecut = 40 / intra_refresh = 0 / rc_lookahead = 40 / rc = crf / mbtree = 1 / crf = 23.0 / qcomp = 0.60 / qpmin = 0 / qpmax = 69 / qpstep = 4 / ip_ratio = 1.40 / aq = 1:1.00\",\"extra\": {\"codecconfigurationbox\": \"avcc\"}},{\"@type\": \"audio\",\"streamorder\": \"1\",\"id\": \"2\",\"format\": \"aac\",\"format_settings_sbr\": \"no (explicit)\",\"format_additionalfeatures\": \"lc\",\"codecid\": \"mp4a-40-2\",\"vidSeconds\": \"31.781\",\"vidSeconds_lastframe\": \"-0.030\",\"bitrate_mode\": \"cbr\",\"bitrate\": \"128320\",\"channels\": \"2\",\"channelpositions\": \"front: l r\",\"channellayout\": \"l r\",\"samplesperframe\": \"1024\",\"vidAudio\": \"22050\",\"samplingcount\": \"700771\",\"vidFrameRate\": \"21.533\",\"framecount\": \"685\",\"compression_mode\": \"lossy\",\"streamsize\": \"509766\",\"streamsize_proportion\": \"0.05541\",\"default\": \"yes\",\"alternategroup\": \"1\"}]}}";
        dynamic o = serializer.Deserialize<dynamic>(s);
        return o;
    }
Velocedge
  • 1,222
  • 1
  • 11
  • 35
  • 2
    Code you've shown (`((dynamic)o["media"]["track"][1]["@type"]`) can't give that **compile time** error. Please review the question and post actual [MCVE]. – Alexei Levenkov May 24 '21 at 17:54
  • I'm unable to reproduce your problem from scratch. Please fix the post so that it includes a proper [mcve]. Make sure you are clear about what C#/Visual Studio version you're using. – Peter Duniho May 24 '21 at 17:55
  • Edited to specify VS 2019 and clarify that it's a run-time error, not compile time. I'll have to think a bit on how to create a MRE and repost. – Velocedge May 24 '21 at 18:04
  • You would only get that runtime error in the caller but not the callee if something is modifying the object or replacing it entirely between the two statements trying to use it. There seems to be some critical details missing from even the code you posted. – Peter Duniho May 24 '21 at 18:11
  • One would think that... While the code has been edited to focus on the issue, there is nothing between the return of o in the method and the Debug.Writeline immediately after the call to the method. That is why I'm so confused as to what's going on. – Velocedge May 24 '21 at 18:15
  • Are you sure you're running the code you think you're running and not a previously built version? (Perhaps try cleaning the solution to be sure?) – Neil T May 24 '21 at 18:23
  • 1
    _"While the code has been edited to focus on the issue, there is nothing between the return of o in the method and the Debug.Writeline immediately after the call to the method. "_ -- in a brand new .NT 4.7.2 project (.NET 5 doesn't include `JavaScriptSerializer`), using exactly the data you've posted and exactly the code you've posted, it works fine. You are overlooking some important detail that you have not shared with us. – Peter Duniho May 24 '21 at 18:32
  • _"I'm so confused as to what's going on"_ -- at this point, you need to take a step back and re-evaluated every _assumption_ that you've made, verifying those assumptions until you find the one that was wrong. That will be your bug. – Peter Duniho May 24 '21 at 18:33
  • My mistake... The code doesn't actually have "Debug.Writeline" in it. I was checking the values I posted by printing them in the Immediate Window of the debugger. I assumed it would be the same as Debug.Writline and that's NOT the case. I will edit the original post. I also didn't realize I posted the json with carriage returns and line feeds. I took those out in code as well as the example. – Velocedge May 24 '21 at 18:35
  • I will point out that I am skeptical that you even have `Debug.WriteLine()` calls in your code, because when I use those in a test program (instead of `Console.WriteLine()`, which is what I used for my actual test), an exception is thrown: `"Cannot dynamically invoke method 'WriteLine' because it has a Conditional attribute"`. I.e. `Debug.WriteLine()` is simply not compatible with `dynamic` types at all. – Peter Duniho May 24 '21 at 18:35
  • @PeterDuniho - agree, hence the need to cast to `string` before calling `Debug.WriteLine()`. – Neil T May 24 '21 at 18:38
  • @NeilT: but as the OP has admitted, _they aren't actually even calling `Debug.WriteLine()`_. I.e. just as I suspected all along, they have failed to post **real-world code that actually reproduces the problem**. The code they posted never could have produced the exception they claim to have gotten, and until they provide a proper [mcve], no one should be posting an answer, because there's no way to tell _what_ the actual problem is. – Peter Duniho May 24 '21 at 18:39
  • 1
    Frankly, how this question got even one, never mind _three_ upvotes without any sort of evidence that there's actually a way to reproduce the problem they claim is happening, is beyond me. :( – Peter Duniho May 24 '21 at 18:42
  • _"I type o["media"]["track"][1]["@type"] in the Immediate Window and get the error"_ -- nope. Using the code and data you've provided, that works fine. If you get an error, you are doing something different from what you say you are. Either the code is different, the data is different, or you've typed something other than what you think you've typed into the Immediate window. – Peter Duniho May 24 '21 at 18:47
  • 1
    Please do not post links to videos as a way of supporting the question. **Post actual code**. That is the _only_ thing that makes a question relevant and useful for Stack Overflow. If you cannot post a proper [mcve] that reliably reproduces the problem, then the question does not belong on the site. – Peter Duniho May 24 '21 at 18:55
  • In the video, it's very hard to read the code. It's unclear in which method you are and what signature the method has. – Thomas Weller May 24 '21 at 19:28
  • I understand the need to build an example that fails but apparently I cannot.... It works properly when I build a MRE but when I put that exact code into production, I get the same error. – Velocedge May 24 '21 at 21:38
  • _"It works properly when I build a MRE but when I put that exact code into production, I get the same error"_ -- until you are able to produce a proper [mcve], the question is not useful. You obviously have some aspect that is unique to your production environment, different from the basic scenario. But the expectation on Stack Overflow is that people asking questions will put the effort into identifying _every detail_ that is require to reproduce their problem. It's impossible to know for sure what the problem you have is caused by, when we can't even reproduce the behavior. – Peter Duniho May 24 '21 at 22:43
  • 1
    Thanks for stating the obvious Peter... been working on trying to do that all day... must be awesome living in that tower... – Velocedge May 25 '21 at 01:50

1 Answers1

0

To fix this, I think what you need (subject to some conditions on the input) is to cast to string:

dynamic o = GetMediaInfoJson(filename);
Debug.WriteLine((string)o["media"]["track"][1]["@type"] );   // Here I get the error!

Presumably you want to do something with this value other than just write it to the debug output; you will probably still need to cast to string for that purpose.

I would expect you to need to do the same within the method being called; based on the code you've provided so far I can't explain the difference.

EDIT: The question has now been edited to remove references to Debug.WriteLine().

Neil T
  • 1,794
  • 1
  • 12
  • 21
  • Why not ToString() – Roman Zeleniy May 24 '21 at 18:34
  • This is not the same thing. If you call `ToString()` on an object of type `dynamic`, you'll still have a `dynamic`. See e.g. https://stackoverflow.com/questions/41415458/why-does-dynamic-tostring-return-something-between-a-string-and-not-a-string/41415574 – Neil T May 24 '21 at 18:35
  • It is usefull to see the variable content in WathcWindow - from 1st part o["media"] and then make conclusions I guess – Roman Zeleniy May 24 '21 at 18:37
  • Yes, I'm not really using Debug.Writline, I'm checking it with an "if" statement to see if exists and then using many of the object's properties to process the video. – Velocedge May 24 '21 at 18:42
  • 1
    Ok. In future it might be useful to post what you _are_ really using...! – Neil T May 24 '21 at 18:46