Отражение и кастинг - PullRequest
       12

Отражение и кастинг

1 голос
/ 22 апреля 2009

У меня есть следующий сценарий, за исключением исключения, когда я пытаюсь разыграть:

  1. Я добавил ссылку на проект и импортировал пространство имен проекта.
  2. Строка LoadFile загружает dll, сгенерированную при сборке этого проекта.
  3. Я пытаюсь получить доступ к открытому полю атрибута, который украшает свойство объекта из библиотеки DLL.
  4. Вот текст исключения:

[A] MyNamespace.PropertyMetaDataAttribute не может быть приведен к [B] MyNamespace.PropertyMetaDataAttribute. Тип A происходит от «A, Version = 12.0.0.25, Culture = нейтральный, PublicKeyToken = null» в контексте «LoadFrom» в расположении «C: \ projectA \ bin \ debug \ A.dll». Тип B происходит от 'A, Версия = 12.0.0.25, Культура = нейтральная, PublicKeyToken = null' в контексте 'По умолчанию' в местоположении 'C: \ currentProject \ bin \ debug \ A.dll'.

фрагмент кода:

using MyNamespace; // added project reference to this item

m_Assembly = Assembly.LoadFile(ConfigurationManager.AppSettings["DLL_File_Path"]);

 Type objectType = m_Assembly.GetType(string.Format("{0}.{1}", NAMESPACE_PREFIX, "MyObject"));

 // Crash happens on line below:

 Attribute attr = (Attribute) objectType.GetProperty("Name").GetCustomAttributes(false)[0];

//This is the layout of the object which has the property
 MyObject
 {
    [MyAttribute(Name="FooName")]
    Foo {get;set;}
 }

// This is the definition of the attribute
 MyAttribute :Attribute
 {
    // Want to access the value
    public string Name = string.Empty;
 }

Ответы [ 3 ]

4 голосов
/ 22 апреля 2009

Вроде как

ConfigurationManager.AppSettings["DLL_File_Path"]

Указывает на ту же DLL в другом месте, поэтому среда выполнения .Net пытается загрузить уже загруженную DLL, когда вы пытаетесь ее использовать, система типов взрывается из-за типов, повторяющихся между двумя DLL. .

В соответствии с ошибкой, это местоположение двух DLL

  • C: \ currentProject \ Bin \ Debug \ A.DLL
  • C: \ Projecta \ Bin \ Debug \ A.DLL

Если в решении явно указана ссылка, вы можете попытаться установить для параметра copy local значение False, чтобы при создании решения не копировать результат зависимостей

1 голос
/ 23 апреля 2009

Когда вы загружаете сборку, существуют разные контексты, в которые вы можете загружать типы. Вот почему вы не можете кастовать из одного типа в другой. Вы можете обойти это, используя событие AssemblyResolve (как предлагает jishi), или есть также событие TypeResolve , которое вы можете использовать для возврата правильного типа при его использовании, но я думаю, что вам просто действительно нужно выровнять сборку в соответствии с нужным контекстом и понять, когда и как она загружается, и что подходит именно вам.

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

http://blogs.msdn.com/suzcook/archive/2003/09/19/loadfile-vs-loadfrom.aspx

http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx

Кроме того, если вы хотите посмотреть, как и почему они загружаются, вам следует взглянуть на Журналы Fusion , в которых они настроены для выгрузки всей информации, и она покажет вам информацию о загрузке для сборки. .

1 голос
/ 22 апреля 2009

Если ваша dll уже находится в автоматически найденном пути (current-directory, bin и т. Д.) И загружена, потому что вы ссылались на что-то в этой сборке, ваш LoadFile (вы можете вместо этого использовать LoadFrom) загрузит ту же DLL другой контекст (LoadFrom-context) вместо значения по умолчанию.

Вы должны либо рассмотреть возможность загрузки DLL только один раз, либо попытаться сначала извлечь свою сборку из контекста по умолчанию, чтобы избежать конфликта, посмотрев в AppDomain.CurrentDomain.GetAssemblies ().

Вы даже можете прикрепить обработчик AssemblyResolve-событий к AppDomain.CurrentDomain в качестве запасного варианта, если вы пытаетесь получить доступ к сборке, которая не находится в контексте по умолчанию.

http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve.aspx

AppDomain.CurrentDomain.GetAssemblies () будет содержать сборки из всех контекстов, даже из тех, которые вы загрузили с помощью LoadFrom / LoadFile.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...