使用TypeForwardedToAttribute的正确方法是什么?

Che*_*hen 12 .net c# attributes

我在这篇文章这篇文章中看到了这个属性.当我们需要升级旧系统时,它似乎非常有用.然后我创建一个测试解决方案(其中包含3个项目)以使用此属性.首先是一个名为"Animal"的类库项目.

namespace Animal
{
   public class Dog
   {
      public static string Name = "old version";
   }
}
Run Code Online (Sandbox Code Playgroud)

然后我创建一个控制台应用程序项目,添加"Animal"作为参考,并在Main我有的方法中:

Console.WriteLine(Animal.Dog.Name);
Run Code Online (Sandbox Code Playgroud)

现在它打印"旧版本".大!现在我开始"升级"现有项目.我删除了Dog"Animal" 中的类,添加了另一个名为"AdvancedAnimal"的类库项目,其中包含:

namespace Animal
{
   public class Dog
   {
      public static string Name = "new version";
   }
}
Run Code Online (Sandbox Code Playgroud)

添加"AdvancedAnimal"作为"Animal"中的引用.还AssemblyInfo.cs"动物"的,通过添加改性:

[assembly: TypeForwardedTo(typeof(Animal.Dog))]
Run Code Online (Sandbox Code Playgroud)

从这个属性的用法,从现在开始,所有内容都Animal.Dog被转发到Dog"AdvancedAnimal"中的类(实际上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"的用法,删除它并不重要.你能告诉我我的测试/想法有什么问题吗?

Ram*_*Vel 12

通过MSDN

使用TypeForwardedToAttribute属性将类型从一个程序集移动到另一个程序集,而不会中断针对旧程序集编译的调用方.

但是你要做的是将类型从同一个程序集转发到同一个程序集中的另一个类型.它没有任何意义.

让我们说清楚.假设你在程序集oldAssembly.dll中有一个类狗

namespace Animal
{
   public class Dog
   { 
      public void printName() {      
           console.writeline("old version");
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

并在其他程序集中引用它(x.dll)

   Dog dg=new Dog();
   dg.printName()
Run Code Online (Sandbox Code Playgroud)

以后你想要更改printName功能,但不要触及调用者(x.dll)(假设dll已部署且不想被触摸)

所以你创建了一个新的程序集(dll)

namespace AdvancedAnimal 
{
   public class Dog
   { 
      public void printName() {      
           console.writeline("new version");
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

现在,您现在可以通过添加对新dll的引用并添加来重新编译旧的dll

[assembly:TypeForwardedTo(typeof(AdvancedAnimal.Dog))]
Run Code Online (Sandbox Code Playgroud)

现在无论对Animal.Dog的调用都转发到AdvancedAnimal.Dog.

所以

!我期望修改"Animal",添加"AdvancedAnimal",没有必要更改所有其他项目/类库,因为程序集信息已经提供了足够的信息.升级系统时非常方便.否则,我有20个项目引用"动物",我需要添加"AdvancedAnimal"作为所有这些项目的参考.

您不必将AdvancedAnimal添加到所有20个项目中.您所要做的就是将AdvancedAnimal添加到Animal.

希望这可以澄清它可能有用的背景

编辑:

我重新编译整个解决方案,并希望控制台应用程序打印"新版本".但它给了我一个编译错误:

这一点的全部意义是我们可以在不修改调用者的情况下调用新程序集.您不应该重新编译整个解决方案,因为您的调用者仍然指向旧程序集中的方法.这就是为什么你得到错误

在命名空间"Animal"中找不到类型名称"Dog".此类型已转发到程序集"AdvancedAnimal"

只需重新编译旧的和新的组合并将其放入调用者bin并运行exe.它会像魅力一样工作

  • @拉梅什:明白了!无需重新编译控制台应用程序!原始的“.exe”文件输出“新版本”。我一整天都在尝试编译控制台应用程序,但它一直给我编译错误。哈哈! (2认同)
  • @StingyJack,也许一个现实世界的用例将有助于澄清。在 .NET 3.5 中,“System.Action”被添加到“System.Core”程序集,但在 .NET 4 中,它被移动到“mscorlib”程序集,并在“System.Core”中添加了类型转发器。通过添加该类型转发器,可以将使用该类型针对 .NET 3.5 编译的 dll 加载到 .NET 4 应用程序中。 (2认同)
  • @StingyJack:1)只有开始针对新版本进行编译时,重新编译才会失败2)类型转发器不支持更改命名空间,因此修复编译时问题通常是添加对新程序集的引用3)如果您将类型从“程序集-A”移动到“程序集-B”,其中“程序集-A”依赖于“程序集-B”,那么“程序集-B”可能已经被引用,并且无需更改代码(假设您不通过程序集别名引用类型。) (2认同)
  • 移动类型时必须保留命名空间。那是因为 .NET 通过它们的全名知道您的类型。仅仅保留类名是不够的。使用该属性,您可以简单地移动该类型的代码,将全名保留到另一个程序集。遗憾的是,您无法重命名该类型。 (2认同)