Новое исключение приведения с VS2010 / .Net 4 - PullRequest
0 голосов
/ 25 мая 2010

[Обновлено 25 мая 2010 года] Я недавно обновил VS2008 до VS2010 и в то же время обновился до .Net 4.

Я перекомпилировал существующее решение и столкнулся с исключением Cast, которого раньше не было.

Структура кода проста (хотя фактическая реализация несколько сложнее).

В основном у меня есть:

public class SomeClass : ISomeClass
{
 // Stuff
}

public static class ClassFactory
{
  public static IInterface GetClassInstance<IInterface>(Type classType)
  {
     return (IInterface)Activator.CreateInstance(classType); // This throws a cast exception
  }
}

// Call the factory with:

ISomeClass anInstance = ClassFactory.GetClassInstance<ISomeClass>(typeof(SomeClass));

Игнорируйте «разумность» вышесказанного - он предоставляет только представление о проблеме, а не специфику того, что я делаю (например, параметры конструктора были удалены).

Отмеченная строка вызывает исключение:

Невозможно привести объект типа Namespace.SomeClass для ввода 'Namespace.ISomeClass'.

Я подозреваю, что это может иметь какое-то отношение к дополнительной безопасности DotNet (и, в частности, к явной загрузке сборок, поскольку это то, что делает мое приложение).

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

<runtime>
    <loadFromRemoteSources enabled="true" />
</runtime>

.. но я не уверен, связано ли это.

Обновление

Я вижу (из комментариев), что мой основной код сам по себе не воспроизводит проблему. Не удивительно, я полагаю. Будет сложно определить, какая часть большой 3-уровневой системы CQS имеет отношение к этой проблеме.

Одной из проблем может быть то, что задействовано несколько сборок. Мой статический класс на самом деле является поставщиком фабрики, а SomeClass - фабрикой классов (важно, чтобы фабрики «регистрировались» в приложении через явную загрузку сборки / типа - см. Ниже).

Upfront. Я использую рефлексию, чтобы «зарегистрировать» все фабрики (то есть классы, реализующие определенный интерфейс), и делаю это, когда приложение запускается путем определения соответствующих сборок, загрузки их и добавления их в кеш, используя (по сути) :

Loop over (file in files)
{
    Assembly assembly = Assembly.LoadFile(file);
    baseAssemblyList.Add(assembly);
}

Затем я кеширую доступные типы в этих сборках:

foreach (Assembly assembly in _loadedAssemblyList)
{
  Type[] assemblyTypes = assembly.GetTypes();
  _loadedTypesCache.AddRange(assemblyTypes);
}

А затем я использую этот кеш для выполнения различных операций отражения, включая «регистрацию» фабрик, которая включает в себя циклическое прохождение всех загруженных (кэшированных) типов и поиск тех, которые реализуют (базовый) интерфейс Factory.

В прошлом я сталкивался с подобной проблемой (.Net 3.5, поэтому не совсем такой) с архитектурой, которая включала динамическое создание классов на сервере и потоковую передачу скомпилированного двоичного файла этих классов в клиентское приложение. , Проблема возникла при попытке десериализации экземпляра динамического класса на клиенте с помощью удаленного вызова: исключение говорит о том, что тип класса не известен, хотя типы источника и назначения были в точности одинаковыми (включая пространство имен). По существу, межграничные версии класса не были признаны одинаковыми. Я решил это путем перехвата процесса десериализации и явного определения типа класса десериализации в контексте локальных сборок.

Этот опыт заставляет меня думать, что типы считаются несовпадающими, потому что (каким-то образом) интерфейс фактического объекта SomeClass и интерфейс, переданный в метод Generic, не считаются одним и тем же типом.

Итак (возможно) мой вопрос для тех, кто более осведомлен о C # / DotNet: как работает загрузка классов, так как мое приложение думает, что есть два варианта / типа интерфейса, и как я могу это исправить (помня это проблема DotNet 3.5 vs 4, как она работала до моего обновления)?

[фу ... кто здесь попал, тот терпеливый .. спасибо]

Ответы [ 2 ]

0 голосов
/ 26 мая 2010

«Быстрое» (внедрение ITO, а не ITO его не обнаружило) решение состояло в том, чтобы остановить теневую копию DLL моего приложения. Это делается путем изменения файла Web.Config приложения ASP.Net следующим образом:

В разделе 'configuration / web.settings' добавьте параметр:

<hostingEnvironment shadowCopyBinAssemblies="false" />
0 голосов
/ 25 мая 2010

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

...