"动态"带有构建器模式的关键字隐藏扩展方法

时间:2016-08-04 13:18:52

标签: c# .net dynamic extension-methods

在我测试某些内容时,我最近遇到了dynamic关键字的奇怪行为。这不是我迫切需要解决的问题,因为我只是在尝试,但我想知道是否有人可以对发生的事情有所了解

我有一个构建器,它在HttpWebRequest上返回一个HttpWebRequest对象和一个扩展方法。

我的一个构建器方法采用string参数。当我将构建器方法传递给字符串时,整个过程都有效,但是我传递了一个dynamic变量,这是一个不再有效的字符串。

似乎返回类型HttpWebRequestBuilder的构建器方法现在返回dynamic

下面的代码很简单,可以重现它,也可以使用here

注意

要使其有效,请注释掉.SetBody(dynamicString)行并取消注释.SetBody(json)行。

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

我猜这是dynamic个对象工作方式的奇怪之处。但任何解释都会非常感激。

2 个答案:

答案 0 :(得分:7)

这是因为传递dynamic参数会使C#编译器将表达式的返回类型(即.SetBody(dynamicString))视为dynamic(相关explanation of method return types with dynamic parameters)。

扩展方法只能作为常规方法使用dynamic个对象,而不是扩展方法(请参阅Eric Lippert's answer以获得解释),因此会看到编译时错误。

答案 1 :(得分:1)

尽管dasblinkenlight的答案似乎是正确的,但请记住,您可以通过以下方式重新编写代码来避免此问题:

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