0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C#のTypeForwardedToについて調べた

Last updated at Posted at 2020-01-31

はじめに

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.dllProgram.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.exeAssemblyBの参照エラーで起動できなかった。なぜ.NET Frameworkでは参照できるのか全く理解していない。
  • 初投稿なのに地味。反省したい。

参考にしたもの

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?