好。我想通了。
我创建了一个自定义Web请求模块,该模块在WebRequest.Create工厂返回之前显式设置HttpWebRequest的用户代理。
首先,创建一个实现IWebRequestCreate的类:
public class CustomHttpRequestCreator : IWebRequestCreate { public CustomHttpRequestCreator(){} public WebRequest Create(Uri uri) { HttpWebRequest webRequest = Activator.CreateInstance(typeof(HttpWebRequest), BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { uri, null }, null) as HttpWebRequest; webRequest.UserAgent = "OMG IT WORKED!"; return webRequest; } }
您需要签署此程序集并将其添加到GAC。
现在在您机器上的machine.config中,添加以下配置部分:
<system.net> <webRequestModules> <remove prefix="http:"/> <remove prefix="https:"/> <add prefix="http:" type="HttpWebRequestTest.CustomHttpRequestCreator, HttpWebRequestTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4ba7a6b9db5020b7" /> <add prefix="https:" type="HttpWebRequestTest.CustomHttpRequestCreator, HttpWebRequestTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4ba7a6b9db5020b7" /> </webRequestModules> </system.net>
现在每当有人调用WebRequest.Create时,他们都会得到一个已设置用户代理字符串的HttpWebRequest。
我还尝试创建一个继承自HttpWebRequest的自定义类,但这很棘手,因为没有默认的公共构造函数。唯一的公共构造器是ISerializable的过时实现。
我成功地将我的dervied类与ISerializable构造函数一起使用,但由此产生的“伪水合”对象不处于有效状态,可能是因为ISerializable实现已过时并且未由Microsoft维护。
尽管如此,如果他们在更详细地研究使用它时遇到的错误,那么有可能使这个工作成功。具体而言,ServicePoint相关访问存在问题。使用反射,人们可能能够使事情发挥作用。这是我的实现参考:
public class CustomHttpWebRequest : HttpWebRequest { public CustomHttpWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) { } internal CustomHttpWebRequest(Uri uri) : base(BuildSerializationInfo(uri), new StreamingContext()) { this.UserAgent = "OMG IT WORKED! (Constructor)"; } private static SerializationInfo BuildSerializationInfo(Uri uri) { HttpWebRequest webRequest = Activator.CreateInstance(typeof(HttpWebRequest), BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { uri, null }, null) as HttpWebRequest; var serializationInfo = new SerializationInfo(typeof(HttpWebRequest), new System.Runtime.Serialization.FormatterConverter()); ((ISerializable)webRequest).GetObjectData(serializationInfo, new StreamingContext()); return serializationInfo; } public override WebResponse GetResponse() { this.UserAgent = "OMG IT WORKED!"; return base.GetResponse(); } public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state) { this.UserAgent = "OMG IT WORKED ASYNC!"; return base.BeginGetResponse(callback, state); } }