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.
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.
What you are seeing when you add/remove Silverlight, is portable flipping between two different .NET API surface areas. I cover these two different surface areas here: What is .NET Portable Subset (Legacy)?.
In what we call the legacy surface area, this method lives on Delegate. In the new surface area, this method has been moved to MethodInfo.
Why did we do this?
For layering reasons. In the new surface, reflection types (ie Assembly, MemberInfo, MethodInfo, etc) are considered as living in a higher layer than the core primitives, which includes Delegate. Unlike the legacy surface area (where they all live in mscorlib), these types in different assemblies; System.Reflection.dll and System.Runtime.dll, respectively.
This method (a few others) were causing something at a lower layer (System.Runtime.dll) to depend on something at a higher layer (System.Reflection.dll). To prevent that, the dependency was reversed.