2016-08-04 17 views
6

Ich bin kürzlich auf ein seltsames Verhalten mit dem Schlüsselwort dynamic gestoßen, während ich etwas getestet habe. Dies ist kein Problem, das ich dringend lösen müssen, wie ich gerade experimentiert, aber ich habe mich gefragt, ob jemand auf jeden beleuchten konnte, was geschah"dynamisches" Schlüsselwort mit Builder-Muster verbirgt Erweiterungsmethode

Ich habe einen Baumeister, die ein HttpWebRequest Objekt und eine Erweiterungsmethode auf HttpWebRequest zurückgibt.

Eine meiner Builder-Methoden dauert ein string Argument. Die ganze Sache funktioniert, wenn ich der Builder-Methode eine Zeichenfolge übergebe, aber ich übergebe es eine dynamic Variable, die eine Zeichenfolge ist, die es nicht mehr funktioniert.

Es scheint, als ob die Builder-Methode, die den Typ HttpWebRequestBuilder zurückgeben sollte, dynamic zurückgibt.

Der folgende Code ist ein einfacher, es zu reproduzieren war und ist auch here

Hinweis

Um es .SetBody(json) die Linie .SetBody(dynamicString) und Kommentar- der Linie funktioniert, kommentieren Sie.

public class Program 
{ 
    public static void Main() 
    { 
     dynamic dynamicString = "{ \"test\" : \"value\" }"; 
     string json = "{ \"test\" : \"value\" }"; 

     string test = new HttpWebRequestBuilder() 
      .SetRequestType() 
      //.SetBody(json) //uncomment this and it works 
      .SetBody(dynamicString) //uncomment this and it breaks 
      .Build() 
      .ExtensionMethod(); 

     Console.WriteLine(test); 
    } 

} 

public class HttpWebRequestBuilder 
{ 
    private readonly HttpWebRequest _request; 

    public HttpWebRequestBuilder() 
    { 
     Uri uri = new Uri("http://www.google.com"); 
     _request = WebRequest.CreateHttp(uri); 
    } 

    public HttpWebRequestBuilder SetRequestType() 
    { 
     _request.Method = "POST"; 
     _request.ContentType = "application/json"; 

     return this; 
    } 

    public HttpWebRequestBuilder SetBody(string json) 
    { 
     byte[] bytes = Encoding.UTF8.GetBytes(json); 
     _request.ContentLength = bytes.Length; 

     using (Stream writer = _request.GetRequestStream()) 
     { 
      writer.Write(bytes, 0, bytes.Length); 
      writer.Flush(); 
     } 

     return this; 
    } 

    public HttpWebRequest Build() 
    { 
     return _request; 
    } 
} 

public static class WebRequestExtensions 
{ 
    public static string ExtensionMethod(this HttpWebRequest webRequest) 
    { 
     return "extension method worked"; 
    } 
} 

Ich vermute, das ist etwas seltsam mit der Art und Weise ist dynamic Objekten arbeiten. Aber jede Erklärung würde sehr geschätzt werden.

Antwort

7

Dies geschieht, weil Hindurchleiten einen dynamic Parameters C macht # Compiler den Rückgabetyp des Ausdrucks Behandlung, d.h. .SetBody(dynamicString), wie dynamic (relevant explanation of method return types with dynamic parameters).

Erweiterungsmethoden arbeiten mit dynamic Objekte nur als reguläre Methoden, nicht als Erweiterungsmethoden (siehe Eric Lippert's answer für eine Erklärung dieser), daher der Kompilierungsfehler, den Sie sehen.

+0

las ich diese Antwort von eric in Vergangenheit, aber ich total vergessen darüber:/ –

1

Obwohl die Antwort von dasblinkenlight scheint richtig zu sein, denken Sie bitte daran, dass Sie immer dieses Problem vermeiden kann Ihren Code auf diese Weise durch die Neuformulierung:

public class Program 
{  public static void Main() 
    { 
     dynamic dynamicString = "{ \"test\" : \"value\" }"; 
     string json = "{ \"test\" : \"value\" }"; 

     var test = new HttpWebRequestBuilder(); 
      test.SetRequestType(); 
      //test.SetBody(json); //still works 
      test.SetBody(dynamicString); // works also now 
      var b = test.Build(); 
      var s = b.ExtensionMethod(); 

     Console.WriteLine(s); 
    } 
} 
+0

Danke dafür, ich hatte tatsächlich etwas Ähnliches gemacht, um herumzukommen, als ich testete. Die Frage war mehr für mich zu verstehen, warum es passierte. Dies könnte für jemand anderen hilfreich sein, also gebe ich ein +1 auf – Dreagen