はじめに
System.Runtime.CompilerServicesに定義されているTypeForwardedFromAttribute
とは何なのか、なんとなく調べた。
"なんとなく"というのは何とはなしにということではなく、あいまいに調べたということです。
一言でいうと
アセンブリ内に定義された型情報を別のアセンブリに転送するしくみ。
書いてみた
実行環境はVisual Studio 2019/.NET Framework 4.7.2
こういうクラスライブラリ(アセンブリ)があったとする。
// AssemblyA.dll
using System;
namespace Foo
{
public static class Bar
{
public static void Print() => Console.WriteLine("I'm Bar A.");
}
public static class Baz
{
public static void Print() => Console.WriteLine("I'm Baz A");
}
}
こういう風に使ったとする。
// Program.exe
namespace ForwardToTest
{
class Program
{
static void Main(string[] args)
{
Foo.Bar.Print();
Foo.Baz.Print();
}
}
}
Program.exeを実行すると当然こう出力される。
I'm Bar A.
I'm Baz A.
ここで、Foo.BarクラスをAssemblyA.dllから別のアセンブリ(AssemblyB.dll)に移動させたい気分になったとする。
まずAssemblyBに次のように書く。
// AssemblyB.dll
using System;
namespace Foo
{
public static class Bar
{
public static void Print() => Console.WriteLine("I'm Bar B.");
}
}
AssemblyAプロジェクトにAssemblyBへの参照を追加し、AssemblyAを次のように修正する。
// AssemblyA.dll
using System;
// TypeForwadedToによりAssemblyBのFoo.Barへ転送される
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Foo.Bar))]
namespace Foo
{
public static class Baz
{
public static void Print() => Console.WriteLine("I'm Baz A");
}
}
AssemblyAをリビルドし、AssemblyA.dll, AssemblyB.dllをProgram.exeのあるディレクトリにコピーする。
Program.exeを実行すると出力が次のように変わる。
I'm Bar B.
I'm Baz A.
何のためにあるのか?
ドキュメントによると
Use the TypeForwardedToAttribute attribute to move a type from one assembly to another without disrupting callers that compiled against the old assembly.
古いアセンブリでコンパイルされたcaller(上の例ではProgram.exe)に手を加えず、型を別のアセンブリに移動できる。
ライブラリ製作者はとてもありがたいのだと思う。
TypeForwadedFromもある
どのアセンブリから転送される可能性があるのか、メタ情報として持たせることができる。
上のAssemblyBだと
// AssemblyB.dll
using System;
namespace Foo
{
[System.Runtime.CompilerServices.TypeForwardedFrom("OldAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")]
public static class Bar
{
public static void Print() => Console.WriteLine("I'm Bar B.");
}
}
こういうふうに属性をつける。
適当な文字列を書いてもビルドエラーやランタイムエラーになったりはしないようなので、ただのメモみたいなもの・・・?
備考
- はじめ
.NET Coreでやろうとして、ただdllを置き換えただけではProgram.exeがAssemblyBの参照エラーで起動できなかった。なぜ.NET Frameworkでは参照できるのか全く理解していない。 - 初投稿なのに地味。反省したい。
参考にしたもの