2015-07-17 2 views
2

У меня есть код отражения, и я хотел бы иметь способ привязать имена методов к типам вместо объявления через строки.Есть ли типизированный способ объявить имя метода в C#

У меня есть этот интерфейс:

interface IDoStuff<T> { 
    void Do(T stuff); 
} 

Тогда у меня есть этот код:

object stuff = GotThisFromSomewhereElse(); 
object doer = GotThisFromSomewhereElseAlso(); 
var doMethodInfo = doer.GetType().GetMethod("Do"); 
doMethodInfo.Invoke(doer, new[] { stuff }); 

Проблема в том, что я не могу просто сделать безопасный бросок и назвать его, потому что это общий и я на самом деле не знаю, какой тип T.

Это прекрасно работает, но когда я переименую метод, я должен обновить его, я не слишком обеспокоен тем, что у меня есть тесты, подтверждающие все эти работы, которые защищают от того, что они не знают, что это изменилось.

Это просто очень уродливо, и мне было любопытно, есть ли какой-нибудь пятнистый способ напечатать его и, таким образом, он будет переименован ReSharper, если я его изменю.

Я бы очень хотел что-то вроде:

object stuff = GotThisFromSomewhereElse(); 
object doer = GotThisFromSomewhereElseAlso(); 
var doMethodInfo = doer.GetType().Methods.Do; 
doMethodInfo.Invoke(doer, new[] { stuff }); 

Спасибо заранее и, пожалуйста, дайте мне знать, если это то, что возможно в C#.

+1

Короткий ответ: нет. Отражение - это все, что нужно делать динамично. Если вам нужна безопасность типа, вам нужно найти способ сделать это без отражения. – dman2306

+0

Действительно; если Resharper смог переименовать метод автоматически, вам не нужно было бы отражать его, чтобы вызвать его в первую очередь. (Тем не менее, может быть, вы не нуждаетесь в размышлении, и вы еще не справились с этим ...) –

ответ

0

Создать общий метод DoIt:

private void DoIt<T>(T stuff, IDoStuff<T> doer) { 
    doer.Do(stuff); 
} 

и называют его:

DoIt(GotThisFromSomewhereElse(), GotThisFromSomewhereElseAlso()); 

Конечно, GotThisFromSomewhereElseAlso и GotThisFromSomewhereElse должны быть дженериков, а также.

7

Начиная с C# 6, вы сможете избежать волшебную строку, используя новый nameof заявление:

IDoStuff<object> dummy = null; // don't need a valid instance. 
string methodName = nameof(dummy.Do) // yay! no magic strings. 

EDIT: @ 31eee384 отметил в комментариях, что выше, может быть еще более упрощен как это:

string methodName = nameof(IDoStuff<object>.Do); 

О новом nameof заявлении documentation это сказать, что, кажется, очень хорошо согласуется с тем, что ОП пытается выполнить:

Вы часто хотите захватить имя строки метода. Использование nameof помогает сохранить код при переименовании определений. Прежде чем вам пришлось использовать строковые литералы для обозначения определений, которые хрупки при переименовании элементов кода, потому что инструменты не знают, чтобы проверить эти строковые литералы.


Перед C# 6, это также возможно, чтобы избежать магических строк с помощью выражений, но это немного clunkier. Вот пример, который будет работать в вашем случае.

Во-первых, вы пишете следующий метод расширения:

public static string GetMethodName<T>(this T instance, Expression<Action<T>> methodExpression) 
{ 
    if (methodExpression.Body is MethodCallExpression) 
    { 
     return ((MethodCallExpression)methodExpression.Body).Method.Name; 
    } 
    else 
    { 
     throw new ArgumentException(string.Format("Invalid method expression: {0}", methodExpression.Body)); 
    } 
} 

И тогда вы можете использовать его как это:

IDoStuff<object> dummy = null; // don't need a valid instance. 
string methodName = dummy.GetMethodName(t => t.Do(null)); // yay! still no magic strings. 
+0

С помощью 'nameof' вы можете использовать имя типа вместо экземпляра для доступа к имени поля/метода , поэтому вам не нужно создавать манекен. Например. 'Nameof (Cow.Moo)'. Нет источника, но я просто попробовал. (И если код в 'Cow', просто' nameof (Moo) 'даже в статическом методе.) – 31eee384

+0

@ 31eee384: Спасибо, что указали это. К сожалению, у меня нет средств проверить это. Вы знаете, как это работает для родового типа? Будет ли он написан как 'nameof (IDoStuff.Do)' или 'nameof (IDoStuff .Do)' или 'nameof (IDoStuff .Do)'? Я очень хочу получить доступ к новой версии C# /. NET.VS! – sstan

+1

Я пробовал несколько вариантов, но только скомпилирован с такими «полными» типами, как 'nameof (IDoStuff .Do)' во внешних классах. [Вот несколько примеров. (Прокомментированные не компилируемые.)] (Https://gist.github.com/anonymous/7c430563a26dd6377339) Да, C# 6 - потрясающая куча улучшений. – 31eee384

Смежные вопросы