48

I want expose WebClient.DownloadDataInternal method like below:

[ComVisible(true)]
public class MyWebClient : WebClient
{
    private MethodInfo _DownloadDataInternal;

    public MyWebClient()
    {
        _DownloadDataInternal = typeof(WebClient).GetMethod("DownloadDataInternal", BindingFlags.NonPublic | BindingFlags.Instance);
    }

    public byte[] DownloadDataInternal(Uri address, out WebRequest request)
    {
        _DownloadDataInternal.Invoke(this, new object[] { address, out request });
    }

}

WebClient.DownloadDataInternal has a out parameter, I don't know how to invoke it. Help!

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
ldp615
  • 932
  • 1
  • 9
  • 13

2 Answers2

129

You invoke a method with an out parameter via reflection just like any other method. The difference is that the returned value will be copied back into the parameter array so you can access it from the calling function.

object[] args = new object[] { address, request };
_DownloadDataInternal.Invoke(this, args);
request = (WebRequest)args[1];
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • The first line cann't be compiled. – ldp615 Mar 14 '10 at 01:39
  • what would happen if there is another overloaded method??? -------1-------- int test(int i, out string s) { s = ""; return 0; } -------------- and ----------- int test(int i) { return 0; } – MrClan Feb 28 '12 at 01:55
  • 9
    If you are using a version of `Invoke` that requires the type parameters be passed, then be sure to use the `Type.MakeByRefType` instance method for the output parameter. (Not relevant here, but was in my case!) – Kenneth K. Jan 24 '13 at 22:05
  • 1
    You can first choose the overload in that type (with `Type::GetMethods` etc), and then invoke the specific method from its `MethodInfo::Invoke`. Saves the problem with overloads, parameter type lists, etc. Also you get method resolution errors separated from invocation errors -- very nice if smth goes wrong. – hypersw Jan 09 '14 at 22:38
23
public class MyWebClient : WebClient
{
    delegate byte[] DownloadDataInternal(Uri address, out WebRequest request);

    DownloadDataInternal downloadDataInternal;

    public MyWebClient()
    {
        downloadDataInternal = (DownloadDataInternal)Delegate.CreateDelegate(
            typeof(DownloadDataInternal),
            this,
            typeof(WebClient).GetMethod(
                "DownloadDataInternal",
                BindingFlags.NonPublic | BindingFlags.Instance));
    }

    public byte[] DownloadDataInternal(Uri address, out WebRequest request)
    {
        return downloadDataInternal(address, out request);
    }
}
dtb
  • 213,145
  • 36
  • 401
  • 431
  • Syntactic sugar for the barebones solution by @JaredPar. Clean and useful for readability and testing. +1 – IAbstract Dec 27 '20 at 11:24