好的。我想通了。
我创建了一个自定义 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 的过时实现。
我成功地让我的派生类与 ISerializable 构造函数一起使用,但生成的“伪水合”对象未处于有效状态,这可能是因为 ISerializable 实现已过时且尚未维护由微软提供。
不过,如果他们更详细地调查使用它时遇到的错误,则有可能完成这项工作。具体来说,与 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);
}
}