メソッド呼び出し時にログを出力してみたいなと探したところ、Autofacというライブラリを使えば、.NET Coreでも行けそうだということで試してみました。
このライブラリそのものはIoCのためのライブラリです。
やってみた感触としては、
- 出力したいメソッドにvirutalの指定が必要で、これが微妙。
- internalなクラスに適用するためにフレンドアセンブリの指定が必要。
でした。
using System; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using Autofac; using Autofac.Extras.DynamicProxy; using Castle.DynamicProxy; // internalなクラスにも適用出来るためフレンドアセンブリの指定が必要。 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] namespace ConsoleApp2 { class Program { static void Main(string[] args) { var builder = new ContainerBuilder(); builder.RegisterType<First>() .EnableClassInterceptors(); builder.Register(c => new CallLogger(Console.Out)); var container = builder.Build(); using (var scope = container.BeginLifetimeScope()) { var first = scope.Resolve<First>(); first.GetValue(); Console.WriteLine("Hello World!"); } } } [Intercept(typeof(CallLogger))] internal class First { public virtual int GetValue() { return 5; } } public class CallLogger : IInterceptor { readonly TextWriter _output; public CallLogger(TextWriter output) { _output = output; } public void Intercept(IInvocation invocation) { _output.Write("Calling method {0} with parameters {1}... ", invocation.Method.Name, string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())); invocation.Proceed(); _output.WriteLine("Done: result was {0}.", invocation.ReturnValue); } } }
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.2</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Autofac.Extras.DynamicProxy" Version="4.5.0" /> <PackageReference Include="Castle.Core" Version="4.4.0" /> </ItemGroup> </Project>
仕組みとしては、DIを解決して生成されたオブジェクトは、指定されたクラスの純粋のインスタンスではありません。
MethodIntercepterで指定されたメソッドを注入したオブジェクトになります。