Из моего комментария к ОП:
Я бы избегал расширенного использования отражений, если вы беспокоитесь о производительности.Если вы можете придумать интерфейс для класса (ов), который вы используете, то я бы создал его.Затем напишите оболочку, которая реализует интерфейс, вызвав код SharpBreak, и поместите его в отдельную DLL.Затем динамически загрузите только свою сборку обертки и конкретные типы обертки и вызовите этот интерфейс.Тогда вам не нужно делать отражения на уровне метода.
Я не уверен, что все классы вам понадобятся, но вот простой пример того, как вы можете подключиться к этой библиотеке с помощьюслабая связь на основе интерфейсов.
в сборке вашей программы:
public IExtensions
{
void SendToAirbrake(Exception exception);
}
public static AirbreakExtensions
{
private static IExtensions _impl;
static()
{
impl = new NullExtensions();
// Todo: Load if available here
}
public static void SendToAirbrake(this Exception exception)
{
_impl.SendToAirbrake(exception);
}
}
internal class NullExtensions : IExtensions // no-op fake
{
void SendToAirbrake(Exception exception)
{
}
}
в сборке с возможностью загрузки (через отражения)
public ExtensionsAdapter : IExtensions
{
void SendToAirbrake(Exception exception)
{
SharpBrake.Extensions.SendToAirbrake(exception);
}
}
Преимущество этого подхода состоит в том, что вы используете отражения только один раз (под нагрузкой) и никогда не трогаете их снова.Также легко изменить, чтобы использовать внедрение зависимостей или фиктивные объекты (для тестирования).
Редактировать:
Для других типов это займет немного больше работы.
Возможно, вам потребуется использовать шаблон Abstract Factory для создания экземпляра AirbrakeNoticeBuilder
, поскольку вам нужно иметь дело непосредственно с интерфейсом и не можете помещать конструкторы в интерфейсы.
public interface IAirbrakeNoticeBuilderFactory
{
IAirbrakeNoticeBuilder Create();
IAirbrakeNoticeBuilder Create(AirbrakeConfiguration configuration);
}
Если вы имеете дело с пользовательскими структурами Airbreak, у вас будет еще больше работы.
Например, для AirbrakeNoticeBuilder
вам придется создавать дубликаты типов POCO для любых связанных классов, которые выuse.
public interface IAirbrakeNoticeBuilder
{
AirbrakeNotice Notice(Exception exception);
}
Поскольку вы возвращаете AirbrakeNotice
, вам, возможно, придется загружать почти все POCO в папке Serialization, в зависимости от того, сколько вы используете, и сколько вы передаете обратно в платформу.
Если вы решите скопировать код POCO, включая все дерево объектов, вы можете изучить использование AutoMapper для преобразования в и из ваших копий POCO .
Альтернативно, если вы не используете йЕсли вы возвращаете значения в классы, которые вы возвращаете, и просто передаете их обратно в код SharpBreak, вы можете придумать некую непрозрачную схему ссылок, которая будет использовать словарь непрозрачного ссылочного типа для фактического типа POCO.Тогда вам не нужно копировать все дерево объектов POCO в ваш код, и вам не нужно тратить слишком много времени на выполнение, чтобы отобразить деревья объектов назад и вперед:
public class AirbrakeNotice
{
// Note there is no implementation
}
internal class AirbreakNoticeMap
{
static AirbreakNoticeMap()
{
Map = new Dictionary<AirbreakNotice, SharpBreak.AirbreakNotice>();
}
public static Dictionary<AirbreakNotice, SharpBreak.AirbreakNotice> Map { get; }
}
public interface IAirbrakeClient
{
void Send(AirbrakeNotice notice);
// ...
}
internal class AirbrakeClientWrapper : IAirbrakeClient
{
private AirbrakeClient _airbrakeClient;
public void Send(AirbrakeNotice notice)
{
SharpBreak.AirbrakeNotice actualNotice = AirbreakNoticeMap.Map[notice];
_airbrakeClient.Send(actualNotice);
}
// ...
}
internal class AirbrakeNoticeBuilderWrapper : IAirbrakeNoticeBuilder
{
AirbrakeNoticeBuilder _airbrakeNoticeBuilder;
public AirbrakeNotice Notice(Exception exception)
{
SharpBreak.AirbrakeNotice actualNotice =
_airbrakeNoticeBuilder.Notice(exception);
AirbrakeNotice result = new AirbrakeNotice();
AirbreakNoticeMap.Map[result] = actualNotice;
return result;
}
// ...
}
Имейте в видучто вам нужно только обернуть классы и части открытого интерфейса, который вы собираетесь использовать.Объект все равно будет вести себя так же внутри, даже если вы не закроете весь его открытый интерфейс.Это может означать, что вам придется выполнять меньше работы, поэтому подумайте и постарайтесь обернуть только то, что вам нужно сейчас, и то, что, как вы знаете, вам понадобится в будущем.Помните ЯГНИ .