はじめに
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
では参照できるのか全く理解していない。 - 初投稿なのに地味。反省したい。
参考にしたもの