Избегайте создания фиктивной переменной для принудительной загрузки сборки.NET

Фон:

У меня есть приложение.NET 4.5, которое использует Enterprise Library 6.0 для подключения к базе данных Oracle. Чтобы использовать поставщик данных Oracle для.NET, вы должны использовать EntLibContrib.Data.OdpNet.

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

Выпуск:

Я пошел использовать сборки в другом проекте (в другом решении) и столкнулся с проблемами. Я добавил ссылки на следующее:

  • .NET библиотеки, созданные с помощью другого решения
  • Microsoft.Practices.EnterpriseLibrary.Common
  • Microsoft.Practices.EnterpriseLibrary.Data
  • EntLibContrib.Data.OdpNet

После добавления соответствующих настроек в конфигурацию он должен был работать так же, как и в других проектах, но когда я попытался подключиться к базе данных, я получил следующую ошибку:

Тип 'EntLibContrib.Data.OdpNet.OracleDatabase, EntLibContrib.Data.OdpNet' не может быть разрешен. Пожалуйста, проверьте правильность написания или укажите полное имя типа.

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

Поскольку я снова столкнулся с этой проблемой, я исследовал и сузил ее, что мне нужно иметь ссылку на объект, который был частью EntLibContrib.Data.OdpNet. Это также работает, если у меня есть ссылка на объект, который ссылается на объект, который является частью EntLibContrib.Data.OdpNet.

Моим решением было просто написать фиктивную переменную в классе моего нового проекта:

private static EntLibContrib.Data.OdpNet.OracleDataReaderWrapper dummyVarNotUsed; 

Даже если dummyVarNotUsed никогда не используется, просто наличие этой строки позволяет правильно ссылаться на сборку EntLibContrib.Data.OdpNet.

Это хак, может кто-нибудь пролить свет на то, что происходит и как лучше ссылаться на dll?

1 ответ

Решение

Исходя из этого вопроса и связанного с ним ответа, я бы предложил попробовать разобраться с AssemblyResolve событие, так что-то вроде этого:

//in your startup method
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

//...
private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
    //not sure if this will be what the name is, you'd have to play with it
    if (args.Name == "EntLibContrib.Data.OdpNet.OracleDatabase")
    {
        return typeof(EntLibContrib.Data.OdpNet.OracleDataReaderWrapper).Assembly;
    }
    //not sure if this is best practice or not (to return null if truly unknown)
    return null;
}

Этот ответ действительно предлагает ваше текущее решение в качестве предпочтительного метода, но я согласен, что оно кажется хакерским. Не уверен, что этот другой метод покажется вам менее удачным; это делает для меня то, что, по крайней мере, таким образом вы можете четко задокументировать этот обработчик событий вместо фиктивной переменной где-нибудь с комментариями вроде //DON'T REMOVE, VERY IMPORTANT!!!

Другие вопросы по тегам