为什么我不能在我的可移植类库中调用Delegate.CreateDelegate?

我有以下问题:我想从我的针对.NET 4.5,Windows Phone 8和Windows 8 Store Apps的可移植类库中调用Delegate.CreateDelegate ,但我的代码无法编译。 编译器说它无法在Delegate类型上找到该方法。

有趣的是,例如Microsoft的PRISM库可以从便携式类库中调用’Delegate.CreateDelegate’。 它在DelegateReference类中执行此操作。 PRISM便携式类库面向.NET 4.0,Windows 8商店应用程序,Windows Phone 8和Silverlight 5(因此是一个更具限制性的集合)。

不编译的代码如下所示:

 public class MyClass { public void MyMethod(EventHandler handler) { var @delegate = Delegate.CreateDelegate(typeof (OpenEventHandler), null, handler.GetMethodInfo()); } } public delegate void OpenEventHandler(T target, object sender, EventArgs arguments); 

可以在此处下载示例: https : //dl.dropboxusercontent.com/u/14810011/PortableClassLibraryReferenceProblem.zip

它包含我的库项目和PRISM PubSubEvents项目的非常剥离版本,该项目仅包含DelegateReference类及其接口。 后者的完整源代码可以在这里找到: http : //prismwindowsruntime.codeplex.com/SourceControl/latest

如何使用所有Delegate成员? 预先感谢您的帮助!

在亨克霍尔特曼的答案之后编辑

GetMethodInfo()是PCL子集支持的扩展方法。 无论如何,这与我不能在PRISM的PCL项目中调用Delegate.CreateDelegate的问题无关。

不编译的代码图片

在Hans Passants评论之后编辑2

我只是玩了一遍,发现当我激活Silverlight 5作为可移植库的目标时,然后可以访问Delegate.CreateDelegate (并且不再使用GetMethodInfo扩展方法)。 然后, Delegate.CreateDelegate是否可以在内部映射到Windows 8 Store和Phone应用程序的另一个API? 这是我能想到如何突然访问此方法的唯一方法,因为我将Silverlight 5添加为有效目标。

(您可以通过右键单击“MyPortableClassLibrary”项目,单击“属性”并在“库”选项卡中单击更改以选择可移植库所针对的框架来重现此操作。)

此外,今天早些时候,我创建了一个Windowsapp store应用项目, CreateDelegate .NET for Windows运行时的Delegate类中没有定义CreateDelegate方法。

在我的实际项目中,我不希望以Silverlight 5为目标,因为我使用Rx大量使用IObservableIObserver并且这些接口未在Silverlight中定义。

您在添加/删除Silverlight时看到的内容是可移植在两个不同的.NET API表面区域之间翻转。 我在这里介绍了这两个不同的表面区域: 什么是.NET Portable Subset(Legacy)? 。

在我们称之为遗留表面区域的方法中,此方法存在于Delegate中。 在新的表面区域中,此方法已移至MethodInfo。

我们为什么这样做?

出于分层的原因。 在新表面中,reflection类型(即Assembly,MemberInfo,MethodInfo等)被认为生活在比核心基元更高的层中,其中包括Delegate。 与传统的表面区域(它们都存在于mscorlib中)不同,这些类型在不同的组件中; 分别是System.Reflection.dll和System.Runtime.dll。

这个方法(其他一些)导致较低层(System.Runtime.dll)的某些东西依赖于更高层的东西(System.Reflection.dll)。 为了防止这种情况,依赖性被逆转了。

好吧,经过一夜的睡眠后,我发现我的问题实际应该是“如何在Windows运行时引入的新API中动态创建委托?” 。 正如Rafael在我的问题评论中指出的那样,除了.NET之外,当Windows 8 / Phone 8被定位时,会提供不同的API。 如果Silverlight也是目标,那么将映射Windows 8 / Phone 8中不可用的API,这解释了当我将Silverlight添加为可移植类库的目标时,我可以突然调用Delegate.CreateDelegate原因。 在.NET中,使用.NET 4.5引入了reflection的新API。

无论如何,要在Windows 8 / Windows Phone 8中创建委托,必须使用MethodInfo.CreateDelegate方法,如下所示:

 public class MyClass { public void MyMethod(EventHandler handler) { var methodInfo = handler.GetMethodInfo(); var @delegate = methodInfo.CreateDelegate(typeof(OpenEventHandler), null); } } public delegate void OpenEventHandler(T target, object sender, EventArgs arguments);