ASP.NET vNext では新しく Assembly Neutral Interfaces という、Roslyn を利用したアセンブリから中立なインターフェースが多く使われるようになりました。
アセンブリ中立なインターフェースって何だ?という感じですが、これが結構面白い仕組みで実現されているので試しました。まずは ASP.NET チームの David Fowler 氏による解説を読んでおきます。
Assembly Neutral Interfaces
Assembly Neutral Types Implementation
後は ASP.NET vNext の Wiki にも同じような説明ですが載ってます。
Home · aspnet/Home Wiki · GitHub
Logger を使った解説が分かりやすいです。要約するとインターフェースだけを集めた Contract なアセンブリを用意する必要なく、それぞれのアセンブリから独立したインターフェースや enum を定義出来る機能です。
TypeScript の Structural Typing のような、違うような。同じ名前空間かつ同じ名前のインターフェースを用意して継承すれば、アセンブリの参照無しでダックタイピング的に使えるようになります。
1.0.0-alpha4 で試す
Visual Studio "14" CTP 4 で実際に使ってみました。まずは vNext ConsoleApp を 1 つと vNext ClassLibrary を 2 つ用意して、それぞれを Console App で参照するように設定しました。
そしてコードは以下のような感じで用意しました。
Class1.cs
namespace ClassLibrary1 { public class Class1 : ConsoleApp1.IGreeting { public string Hello() { return "Hello, Class1"; } } } namespace ConsoleApp1 { [AssemblyNeutral] public interface IGreeting { string Hello(); } [AssemblyNeutral] public class AssemblyNeutralAttribute : Attribute { } }
Class2.cs
namespace ClassLibrary2 { public class Class2 : ConsoleApp1.IGreeting { public string Hello() { return "Hello, Class2"; } } } namespace ConsoleApp1 { [AssemblyNeutral] public interface IGreeting { string Hello(); } [AssemblyNeutral] public class AssemblyNeutralAttribute : Attribute { } }
Program.cs
namespace ConsoleApp1 { public class Program { public static void Main(string[] args) { Greeting(new ClassLibrary1.Class1()); Greeting(new ClassLibrary2.Class2()); Console.ReadLine(); } private static void Greeting(IGreeting obj) { Console.WriteLine(obj.Hello()); } } [AssemblyNeutral] public interface IGreeting { string Hello(); } [AssemblyNeutral] public class AssemblyNeutralAttribute : Attribute { } }
ASP.NET vNext では AssemblyNeutralAttribute という名前の属性が付いている場合、そのクラスやインターフェースはアセンブリから中立なものとして扱われます。
パッと見た感じでは IGreeting インターフェースと AssemblyNeutralAttribute クラスをそれぞれで定義しているのでコンパイルエラーになりそうですが、実際にコンパイルすると問題なく完了します。*1
エディタでは Greeting メソッドに Class1 と Class2 のインスタンスを渡せないエラーが出てますが、実行してみると以下の通り。意図したとおりに実行されました。
このあたりの実装は ASP.NET vNext の Roslyn でカスタマイズされています。基本的に実行時にメタデータをこねこねして正しいインターフェースでの解決が行われるので、かなり祖結合が実現できている感じです。*2
ASP.NET vNext は Assembly Neutral Interfaces 以外にも、様々な新しいテクニックが使われているので、思ったよりもコードを追うのが大変です。