Как правильно использовать TypeForwardedToAttribute? - PullRequest
9 голосов
/ 29 декабря 2010

Я сталкивался с этим атрибутом в этом посте и этом .Кажется, это очень полезно, когда нам нужно обновить старую систему.Затем я создаю тестовое решение (с 3 проектами в нем), чтобы использовать этот атрибут.Во-первых, есть проект библиотеки классов с именем «Animal».

namespace Animal
{
   public class Dog
   {
      public static string Name = "old version";
   }
}

Затем я создаю проект консольного приложения, добавляю «Animal» в качестве ссылки, и в методе Main у меня есть:

Console.WriteLine(Animal.Dog.Name);

Теперь печатается «старая версия».Большой!Теперь я начинаю «модернизировать» существующий проект.Я удаляю класс Dog в «Animal», добавляю еще один проект библиотеки классов с именем «AdvancedAnimal», который содержит:

namespace Animal
{
   public class Dog
   {
      public static string Name = "new version";
   }
}

Добавьте «AdvancedAnimal» в качестве ссылки в «Animal».Также AssemblyInfo.cs из "Animal" модифицируется добавлением:

[assembly: TypeForwardedTo(typeof(Animal.Dog))]

С использованием этого атрибута, теперь все Animal.Dog перенаправляются в класс Dog в "AdvancedAnimal" (фактическив Animal нет класса Dog).Я перекомпилирую все решение и надеюсь, что консольное приложение напечатает «новую версию».Но это дает мне ошибку компиляции:

The type name 'Dog' could not be found in the namespace 'Animal'. This type has been forwarded to assembly 'AdvancedAnimal, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' Consider adding a reference to that assembly.

О, мне сказали добавить «AdvancedAnimal» в качестве ссылки на мое консольное приложение!Но если я сделаю это, мне больше не понадобится атрибут, потому что если я добавлю «AdvancedAnimal» в качестве ссылки в консольном приложении, то, конечно, Animal.Dog ссылается на тот, что в «AdvancedAnimal»!Я ожидаю, что при изменении «Animal», добавлении «AdvancedAnimal», нет необходимости изменять все другие проекты / библиотеки классов, потому что информация о сборке уже предоставляет достаточно информации.Это действительно удобно при обновлении системы.В противном случае у меня есть 20 проектов со ссылкой на «Животное», мне нужно добавить «AdvancedAnimal» в качестве ссылки на все из них.И что еще более важно, я не могу найти никакого использования "TypeForwardedToAttribute" в этом решении, удаление его не имеет значения.Можете ли вы сказать мне, что не так с моим тестом / идеей?

Ответы [ 2 ]

9 голосов
/ 29 декабря 2010

по MSDN

Используйте TypeForwardedToAttribute атрибут для перемещения типа из одного сборка на другой без сбоев абоненты, собранные против старого сборка.

Но вы делаете пересылку типа из той же сборки в другой тип в той же сборке. Это не имеет никакого смысла.

Давай проясним. Предположим, если у вас есть собака класса в сборке oldAssembly.dll

namespace Animal
{
   public class Dog
   { 
      public void printName() {      
           console.writeline("old version");
      }
   }
}

и ссылался на него в другой сборке (x.dll)

   Dog dg=new Dog();
   dg.printName()

позже вы захотели изменить функциональность printName, но не касаясь вызывающей стороны (x.dll) (предположим, что dll развернута и не хочет, чтобы ее трогали)

поэтому вы создаете новую сборку (dll), которая получила

namespace AdvancedAnimal 
{
   public class Dog
   { 
      public void printName() {      
           console.writeline("new version");
      }
   }
}

Теперь вы можете перекомпилировать старую DLL, добавив ссылку на новую DLL и добавив

[assembly:TypeForwardedTo(typeof(AdvancedAnimal.Dog))]

Теперь все вызовы, сделанные в Animal.Dog, перенаправляются в AdvancedAnimal.Dog.

So

! Я ожидаю, что это изменение «Животное», Добавление «AdvancedAnimal», нет необходимо поменять все остальные проекты / библиотеки классов, потому что Информация о сборке уже предоставляет достаточно Информация. Это действительно удобно при обновлении системы. В противном случае я 20 проектов, относящихся к «Животное», мне нужно добавить «AdvancedAnimal» как ссылка на все из них.

Вам не нужно добавлять AdvancedAnimal для всех ваших 20 проектов. Все, что вам нужно сделать, это добавить AdvancedAnimal к Animal.

Надеюсь, это прояснит контекст, в котором это может быть полезно

EDIT:

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

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

Не найдено имя типа «Собака» в пространстве имен «Животное». Этот тип был отправлен на собрание «AdvancedAnimal

Просто перекомпилируйте вашу старую и новую сборку и поместите ее в корзину для вызывающих программ и запустите исполняемый файл. Это будет работать как шарм

1 голос
/ 29 декабря 2010

Впервые слышу об этом атрибуте, интересно :) 1001 *

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

Допустим, у вас есть какое-то приложение, которое использует набор виджетов из DLL. Позже вы решаете переместить части этой DLL в отдельную DLL. Используя TypeForwardedToAttribute, вы можете сделать это, если старая DLL ссылается на новую. Теперь вы можете развернуть обе библиотеки DLL в установках существующего приложения, без перекомпиляции самого приложения

Это может быть полезно в сценариях, где вы не контролируете само приложение, а просто предоставляете набор библиотечных DLL. Чтобы ваша кодовая база двигалась вперед, вы можете использовать TypeForwardedToAttribute, и пользователи могут безопасно развернуть ее в своем приложении, ничего не нарушая.

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