Отражение, особенно в отношении частных лиц, неверно
- Отражение нарушает безопасность типов. Вы можете попытаться вызвать метод, который не существует (больше), или с неправильными параметрами, или с слишком большим количеством параметров, или недостаточно ... или даже в неправильном порядке (это мой любимый :)). Кстати, тип возвращаемого значения также может измениться.
- Отражение медленное.
Разрывы отражения частных членов инкапсуляция принцип и, следовательно, предоставление вашему коду следующего:
- Увеличьте сложность вашего кода, потому что он должен обрабатывать внутреннее поведение классов. То, что скрыто, должно оставаться скрытым.
- Облегчает взлом вашего кода , так как он будет компилироваться, но не будет работать, если метод изменил свое имя.
- Облегчает взлом приватного кода , потому что если он приватный, его не следует называть таким образом. Может быть, закрытый метод ожидает некоторое внутреннее состояние перед вызовом.
Что если я все равно должен это сделать?
Бывают случаи, когда вы зависите от третьей стороны или вам нужно, чтобы какой-то API не был выставлен, вам нужно подумать. Некоторые также используют его для тестирования некоторых классов, которыми они владеют, но они не хотят менять интерфейс, чтобы предоставить доступ к внутренним элементам только для тестов.
Если вы делаете это, делайте это правильно
Чтобы устранить проблему, которую легко сломать, лучше всего обнаружить любой потенциальный сбой путем тестирования в модульных тестах, которые будут выполняться в сборке с непрерывной интеграцией или тому подобном. Конечно, это означает, что вы всегда используете одну и ту же сборку (которая содержит закрытые элементы). Если вы используете динамическую нагрузку и отражение, вам нравится играть с огнем, но вы всегда можете поймать исключение, которое может вызвать вызов.
- Смягчить медлительность отражения:
В последних версиях .Net Framework CreateDelegate в 50 раз превосходил вызов MethodInfo:
// The following should be done once since this does some reflection
var method = this.GetType().GetMethod("Draw_" + itemType,
BindingFlags.NonPublic | BindingFlags.Instance);
// Here we create a Func that targets the instance of type which has the
// Draw_ItemType method
var draw = (Func<TInput, Output[]>)_method.CreateDelegate(
typeof(Func<TInput, TOutput[]>), this);
draw
звонки будут примерно в 50 раз быстрее, чем MethodInfo.Invoke
используйте draw
как стандарт Func
вот так:
var res = draw(methodParams);
Отметьте этот мой пост , чтобы увидеть эталонный тест по различным вызовам методов