これを行う別の方法は、Unity フレームワークによって提供されるような傍受を使用することです。インターセプトを使用すると、クラスはインターフェイスを実装し、そのインターフェイスを実装するクラスでメソッドが呼び出されるたびに、これらのインターセプターを実行するようにフレームワークに指示します。インターセプター コードは、呼び出されているメソッドに set_ というプレフィックスが付いているかどうかを確認できます。インターセプター コードは、関数に向かう途中で 1 回、戻る途中で 1 回実行されます。戻る途中で、インターセプターに filter メソッドを呼び出させることができます (もちろん、インターフェースで定義されていると仮定します)。
具体例:
前提条件ライブラリを取得
NuGet を使用して Unity と Unity 拡張機能をプロジェクトに追加する
インターセプトするインターフェイスを定義します: SomeObject.cs
using System;
namespace InterceptSetter
{
interface ISomeObject
{
string SomeProperty { get; set; }
void Filter();
}
public class SomeObject : ISomeObject
{
public string SomeProperty { get; set; }
public void Filter()
{
Console.Out.WriteLine("Filter Called");
}
}
}
傍受動作を定義します: SetterCallsFilterMethodBehavior.cs
using Microsoft.Practices.Unity.InterceptionExtension;
using System;
using System.Collections.Generic;
using System.Linq;
namespace InterceptSetter
{
/// <summary>
/// See http://msdn.microsoft.com/en-us/library/ff660871(v=pandp.20).aspx
/// See http://msdn.microsoft.com/en-us/library/ff647107.aspx
/// </summary>
class SetterCallsFilterMethodBehavior : IInterceptionBehavior
{
public IEnumerable<Type> GetRequiredInterfaces()
{
// we dont need anything
return new[] { typeof(ISomeObject) };
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{ // Do not intercept non-setter methods
if (!input.MethodBase.Name.StartsWith("set_"))
return getNext()(input, getNext);
IMethodReturn msg = getNext()(input, getNext);
// post processing. this is where we call filter
if (input.Target is ISomeObject)
{
(input.Target as ISomeObject).Filter();
}
return msg;
}
/// <summary>
/// We always execute
/// </summary>
public bool WillExecute
{
get { return true; }
}
}
}
テスト コンソール プログラムを作成します: Program.cs
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using System;
namespace InterceptSetter
{
class Program
{
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterType<ISomeObject, SomeObject>(
new Interceptor<TransparentProxyInterceptor>(),
new InterceptionBehavior<SetterCallsFilterMethodBehavior>());
// we must get our instance from unity for interception to occur
ISomeObject myObject = container.Resolve<ISomeObject>();
myObject.SomeProperty = "Hello Setter";
Console.ReadLine();
}
}
}
これを実行すると、インターセプターが実際にフィルター メソッドを呼び出していることがわかります (コンソールに出力されます)。
依存性注入/インターセプト フレームワークは Unity だけではありません (google PostSharp)。Unity は私がよく知っているものなので、この例ではそれを使用しています。
ソース / 関連項目:
- http://msdn.microsoft.com/en-us/library/ff660871(v=pandp.20).aspx - 傍受の流れを示す良い図
- http://msdn.microsoft.com/en-us/library/ff647107.aspx - さまざまな傍受手法を示す過剰な詳細