Подтвердить что ты не робот

Почему я не могу назвать Delegate.CreateDelegate в моей Portable Class Library?

У меня есть следующая проблема: я хочу вызвать Delegate.CreateDelegate из моей библиотеки Portable Class Library, ориентированной на .NET 4.5, Windows Phone 8 и Windows 8 Store Apps, но мой код не компилируется. Компилятор говорит, что он не может найти метод в типе Delegate.

Самое забавное, что, например, библиотека PRISM от Microsoft может вызвать "Delegate.CreateDelegate" из портативной библиотеки классов. Он делает это в классе DelegateReference. Портативная библиотека классов PRISM предназначена для .NET 4.0, Windows 8 Store Apps, Windows Phone 8 и Silverlight 5 (и, следовательно, еще более ограничивающего набора).

Код, который не компилируется, выглядит следующим образом:

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);

Пример можно скачать здесь: https://dl.dropboxusercontent.com/u/14810011/PortableClassLibraryReferenceProblem.zip

Он содержит проект моей библиотеки и очень разделенную версию проекта PRISM PubSubEvents, содержащего только класс DelegateReference и его интерфейс. Полный исходный код последнего можно найти здесь: http://prismwindowsruntime.codeplex.com/SourceControl/latest

Что я могу сделать, чтобы использовать все члены Delegate? Заранее благодарю вас за помощь!

ИЗМЕНИТЬ после ответа Хенка Холтермана:

GetMethodInfo() - это метод расширения, поддерживаемый подмножеством PCL. Во всяком случае, это не связано с проблемой, которую я не могу назвать Delegate.CreateDelegate, в то время как проект PRISM PCL может.

Picture of code that does not compile

EDIT 2 после комментария Hans Passants:

Я только что поиграл и узнал, что когда я активирую Silverlight 5 как цель переносимой библиотеки, тогда Delegate.CreateDelegate действительно доступен (и метод расширения GetMethodInfo больше не существует). Является ли Delegate.CreateDelegate, а может быть, сопоставлен с другим API для приложений Windows 8 Store и Phone внутри? Это единственный способ, которым я мог бы думать о том, как этот метод будет внезапно доступен только потому, что я добавил Silverlight 5 в качестве действительной цели.

(Вы можете воспроизвести это, щелкнув правой кнопкой мыши по проекту "MyPortableClassLibrary", нажмите "Свойства" и на вкладке "Библиотека" нажмите "Изменить", чтобы выбрать рамки, на которые нацелена переносная библиотека.)

Кроме того, ранее сегодня я создал проект приложения Windows Store и увидел, что не существует метода CreateDelegate, определенного в классе Delegate в .NET для Windows Runtime.

В моем фактическом проекте я не хочу указывать Silverlight 5, поскольку я использую IObservable<T> и IObserver<T> сильно используя Rx, и эти интерфейсы не определены в Silverlight.

4b9b3361

Ответ 1

То, что вы видите, когда вы добавляете/удаляете Silverlight, является переносом между двумя различными областями поверхности API. Я описываю эти две области поверхности: Что такое .NET Portable Subset (Legacy)?.

В том, что мы называем унаследованной поверхностью, этот метод работает на делетете. В новой области поверхности этот метод был перемещен в MethodInfo.

Почему мы это сделали?

Для объяснения причин. На новой поверхности типы отражения (т.е. Assembly, MemberInfo, MethodInfo и т.д.) Рассматриваются как живущие на более высоком уровне, чем основные примитивы, в том числе Делегат. В отличие от старой площади поверхности (где все они живут в mscorlib), эти типы в разных сборках; System.Reflection.dll и System.Runtime.dll соответственно.

Этот метод (несколько других) вызывал что-то на более низком уровне (System.Runtime.dll), чтобы зависеть от чего-то на более высоком уровне (System.Reflection.dll). Чтобы этого избежать, зависимость была отменена.

Ответ 2

ОК, после ночи сна я узнал, что мой вопрос на самом деле должен быть "Как мне динамически создавать делегаты в новом API, представленном с помощью Windows Runtime?" . Как указывал Рафаэль в комментариях к моему вопросу, различные API-интерфейсы предоставляются, когда в Windows 8/Phone 8 используется помимо .NET. Если Silverlight также нацелен, тогда API-интерфейсы, которые недоступны в Windows 8/Phone 8, будут сопоставлены, и это объясняет, почему я могу неожиданно позвонить Delegate.CreateDelegate, когда я добавлю Silverlight в качестве объекта переносимой библиотеки классов. В .NET новые API для Reflection были представлены с .NET 4.5.

В любом случае, чтобы создать делегат в Windows 8/Windows Phone 8, нужно использовать метод MethodInfo.CreateDelegate, как это:

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);