Я пытаюсь создать делегат открытого экземпляра для универсального метода интерфейса, но продолжаю получать NotSupportedException. Вот упрощенный код, который не запускается:
interface IFoo
{
void Bar(T j);
}
class Foo : IFoo
{
public void Bar(T j)
{
}
}
static void Main(string[] args)
{
var bar = typeof(IFoo).GetMethod("Bar").MakeGenericMethod(typeof(int));
var x = Delegate.CreateDelegate(typeof(Action), null, bar);
}
Последняя строка выдает NotSupportedException: «Указанный метод не поддерживается». Для сравнения, неуниверсальный делегат открытого экземпляра работает нормально:
interface IFoo
{
void Bar(int j);
}
class Foo : IFoo
{
public void Bar(int j)
{
}
}
static void Main(string[] args)
{
var bar = typeof(IFoo).GetMethod("Bar");
var x = Delegate.CreateDelegate(typeof(Action), null, bar);
}
И закрытый универсальный делегат также работает:
interface IFoo
{
void Bar(T j);
}
class Foo : IFoo
{
public void Bar(T j)
{
}
}
static void Main(string[] args)
{
var bar = typeof(IFoo).GetMethod("Bar").MakeGenericMethod(typeof(int));
var x = Delegate.CreateDelegate(typeof(Action), new Foo(), bar);
}
Таким образом, рецепт для закрытых универсальных делегатов и делегатов открытого экземпляра работает отдельно, но не в сочетании. Это начинает выглядеть либо как ошибка времени выполнения, либо как преднамеренное упущение. У кого-нибудь есть какие-нибудь идеи?
Microsoft ответила , что это известная проблема, что CLR не может этого сделать, но она не может быть решена в текущей версии .NET. Все еще не совсем ясно , почему это невозможно, как я объясняю там. Открытые делегаты не должны повторно использовать логику диспетчеризации, используемую повсюду в CLR, по какой-то причине, что мне просто кажется странным.
Это резюме темы и этой конкретной проблемы для тех, кто находит этот вопрос (так как кажется, что ОП уже получил свой ответ на Microsoft Connect).
Создание универсального делегата открытого экземпляра для метода универсального интерфейса невозможно (как подтверждено Microsoft здесь ). В настоящее время возможно реализовать любую из следующих комбинаций открытых / закрытых статических, универсальных / неуниверсальных методов интерфейса / класса (с примерами кода, приведенными в конце ответа):
Обычно наилучшей заменой универсального делегата с открытым экземпляром для универсального метода интерфейса является универсальный делегат с открытым экземпляром для универсальный метод класса .
открытый экземпляр неуниверсального делегата для неуниверсального метода интерфейса
interface IFoo
{
void Bar(int j);
}
class Foo : IFoo
{
public void Bar(int j)
{
}
}
static void Main(string[] args)
{
var bar = typeof(IFoo).GetMethod("Bar");
var x = Delegate.CreateDelegate(typeof(Action<IFoo, int>), null, bar);
}
закрыт статический универсальный делегат для универсального метода интерфейса
interface IFoo
{
void Bar<T>(T j);
}
class Foo : IFoo
{
public void Bar<T>(T j)
{
}
}
static void Main(string[] args)
{
var bar = typeof(IFoo).GetMethod("Bar").MakeGenericMethod(typeof(int));
var x = Delegate.CreateDelegate(typeof(Action<int>), new Foo(), bar);
}
закрытый статический неуниверсальный делегат для неуниверсального метода интерфейса
interface IFoo
{
void Bar(int j);
}
class Foo : IFoo
{
public void Bar(int j)
{
}
}
static void Main(string[] args)
{
var bar = typeof(IFoo).GetMethod("Bar");
var x = Delegate.CreateDelegate(typeof(Action<int>), new Foo(), bar);
}
универсальный делегат open instance для метода универсального класса
class Foo
{
public void Bar<T>(T j)
{
}
}
static void Main(string[] args)
{
var bar = typeof(Foo).GetMethod("Bar").MakeGenericMethod(typeof(int));
var x = Delegate.CreateDelegate(typeof(Action<Foo, int>), null, bar);
}
неуниверсальный делегат open instance для метода не универсального класса
class Foo
{
public void Bar(int j)
{
}
}
static void Main(string[] args)
{
var bar = typeof(Foo).GetMethod("Bar");
var x = Delegate.CreateDelegate(typeof(Action<Foo, int>), null, bar);
}
закрытый статический универсальный делегат для метода универсального класса
class Foo
{
public void Bar<T>(T j)
{
}
}
static void Main(string[] args)
{
var bar = typeof(Foo).GetMethod("Bar").MakeGenericMethod(typeof(int));
var x = Delegate.CreateDelegate(typeof(Action<int>), new Foo(), bar);
}
закрытый статический неуниверсальный делегат для метода не универсального класса
class Foo
{
public void Bar(int j)
{
}
}
static void Main(string[] args)
{
var bar = typeof(Foo).GetMethod("Bar");
var x = Delegate.CreateDelegate(typeof(Action<int>), new Foo(), bar);
}