Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

InvalidCastException Dictionary<string, string> using Exception.Data

I have a Client/Server package that I am playing with, I am trying to use Exception.Data to pass custom information into a separate class (ExceptionError) to pass into a MessageBox.

The following catch processes when I try to connect to the server without actually starting up the server to listen for connections. just an oversight on that part, listening for connections is not the actual problem but it shows me the problem with Exception.Data.

catch (Exception e)
{
    e.Data["SourceFile"] = "Client.cs";
    e.Data["MethodName"] = "Send_CommandToServer";
    e.Data["ExceptionType"] = "Exception";
    object[] exceptionArgs = new object[8] { null, e.InnerException, 
                              e.Message, null, e.Source, e.StackTrace, 
                              e.TargetSite, e.Data };
    ExceptionError.Show(exceptionArgs);
}

Here is the line in the ExceptionError Class that is throwing the InvalidCastException:

Dictionary<string,string> data = (Dictionary<string, string>)exceptionArgs[7];
 // exceptionArgs[7] is Exception.Data

Here is the actual Error I am receiving:

Unable to cast object of type 'System.Collections.ListDictionaryInternal' to type 'System.Collections.Generic.Dictionary`2[System.String,System.String]'.

I cannot find anything about ListDictionaryInternal, most of the google searches I have done point to System.Collections.Specialized.ListDictionary which produces issues of its own. Does anyone know anything about ListDictionaryInternal or can you help me with passing e.Data into my ExceptionError Class?

like image 870
roadmaster Avatar asked Dec 11 '22 10:12

roadmaster


2 Answers

Basically, the value of Exception.Data isn't a Dictionary<string, string> - so when you cast it to Dictionary<string, string>, you get this exception.

The property itself is only declared to be of type IDictionary. You shouldn't assume it's a Dictionary<string, string>. You should fix your ExceptionError class to avoid that assumption. It's documented that the keys are typically strings, but that's not guaranteed - likewise it's not guaranteed the the values are strings.

You can perform a "safe" conversion from IDictionary to Dictionary<string, string> by converting only the appropriate entries:

var dictionary = original.Cast<DictionaryEntry>()
                         .Where(de => de.Key is string && de.Value is string)
                         .ToDictionary(de => (string) de.Key,
                                       de => (string) de.Value);
like image 130
Jon Skeet Avatar answered May 10 '23 00:05

Jon Skeet


Exception.Data is typed (and documented) as IDictionary. Also, do not stuff it into an object[]. Instead, preserve the type information and send it as a formal parameter to ExceptionError.Show.

like image 25
usr Avatar answered May 10 '23 00:05

usr