Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I call Delegate.CreateDelegate in my Portable Class Library?

I have the following problem: I want to call Delegate.CreateDelegate from within my Portable Class Library targeting .NET 4.5, Windows Phone 8 and Windows 8 Store Apps, but my code does not compile. The compiler says that it cannot find the method on the Delegate type.

The funny thing is that e.g. the PRISM library by Microsoft can call 'Delegate.CreateDelegate' from a Portable Class Library. It does so in the DelegateReference class. The PRISM portable class library targets .NET 4.0, Windows 8 Store Apps, Windows Phone 8 and Silverlight 5 (and thusly an even more restrictive set).

The code that does not compile looks like this:

public class MyClass
{
    public void MyMethod<T>(EventHandler handler)
    {
        var @delegate = Delegate.CreateDelegate(typeof (OpenEventHandler<T>), null, handler.GetMethodInfo());
    }
}

public delegate void OpenEventHandler<in T>(T target, object sender, EventArgs arguments);

An example can be downloaded here: https://dl.dropboxusercontent.com/u/14810011/PortableClassLibraryReferenceProblem.zip

It contains my library project and a very stripped version of the PRISM PubSubEvents project containing only the DelegateReference class and its interface. The complete source code of the latter can be found here: http://prismwindowsruntime.codeplex.com/SourceControl/latest

What can I do to use all Delegate members? Thank you in advance for your help!

EDIT after Henk Holterman's answer:

GetMethodInfo() is an extension method that is supported by the PCL subset. Anyway, that is not related to the problem that I cannot call Delegate.CreateDelegate while PRISM's PCL project can.

Picture of code that does not compile

EDIT 2 after Hans Passants comment:

I just played around and found out that when I activate Silverlight 5 as a target of the portable library then Delegate.CreateDelegate is indeed accessible (and the GetMethodInfo Extension Method no longer is). Is Delegate.CreateDelegate then maybe mapped to another API for Windows 8 Store and Phone apps internally? It's the only way I could think of how this method would be suddenly accessible just because I added Silverlight 5 as a valid target.

(You can reproduce this by right-clicking on the "MyPortableClassLibrary" project, click "Properties" and in the "Library" tab click change to select the frameworks that are targeted by the portable library.)

Also, earlier today, I created an Windows Store App project and saw that there was no CreateDelegate method defined on the Delegate class in .NET for Windows Runtime.

In my actual project, I do not want to target Silverlight 5 as I use IObservable<T> and IObserver<T> heavily using Rx and these interfaces are not defined in Silverlight.

like image 524
feO2x Avatar asked Aug 09 '13 14:08

feO2x


1 Answers

OK, after a night of sleeping I recognized that my question actually should be "How do I dynamically create delegates in the new API introduced with the Windows Runtime?". As Rafael indicated in the comments of my question, different APIs are provided when Windows 8 / Phone 8 is targeted in addition to .NET. If Silverlight is also targeted, then APIs that are not available in Windows 8 / Phone 8 will be mapped and this explains why I can suddenly call Delegate.CreateDelegate when I add Silverlight as a target of the Portable Class Library. In .NET, the new APIs for Reflection were introduced with .NET 4.5.

Anyway, to create a delegate in Windows 8 / Windows Phone 8, one has to use the MethodInfo.CreateDelegate method, just like this:

public class MyClass
{
    public void MyMethod<T>(EventHandler handler)
    {
        var methodInfo = handler.GetMethodInfo();
        var @delegate = methodInfo.CreateDelegate(typeof(OpenEventHandler<T>), null);
    }
}

public delegate void OpenEventHandler<in T>(T target, object sender, EventArgs arguments);
like image 170
feO2x Avatar answered Nov 04 '22 04:11

feO2x