7

セッターに同じメソッドを実装する複数のプロパティがある場合、それをデフォルトのセッターの一部にする方法はありますか?

設定時にを呼び出す複数のプロパティがある場合、それを「ベースセッター」にプッシュして、すべてのセッターで呼び出すFilter()必要がないようにする方法はありますか?Filter()

private string _MyVal1;
public string MyVal1 {
    get {
        return _MyVal1;
    }
    set {
        _MyVal1 = value;
        Filter();
        OnPropertyChanged("MyVal1");
    }
}

private string _MyVal2;
public string MyVal2 {
    get {
        return _MyVal2;
    }
    set {
        _MyVal2 = value;
        Filter();
        OnPropertyChanged("MyVal2");
    }
}

private string _MyValN;
public string MyValN {
    get {
        return _MyValN;
    }
    set {
        _MyValN = value;
        Filter();
        OnPropertyChanged("MyValN");
    }
}

したがって、これは次のようになります。

private string _MyValN;
public string MyValN {
    get {
        return _MyValN;
    }
    set : FilterSetter {
        _MyValN = value;
        OnPropertyChanged("MyValN");
    }
}
4

2 に答える 2

3

ジェネリック セッター メソッドを作成し、各プロパティ セッターから呼び出すことができます。

private void Set<T>(ref T field, T value, string propertyName)
{
    field = value;
    Filter();
    OnPropertyChanged(propertyName);
}

次に、プロパティは次のようになります。

public string SomeProperty
{
    get { return this.someField; }
    set
    {
        Set(ref this.someField, value, "SomeProperty");
    }
}
于 2013-03-05T15:42:42.697 に答える
3

これを行う別の方法は、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 は私がよく知っているものなので、この例ではそれを使用しています。

ソース / 関連項目:

  1. http://msdn.microsoft.com/en-us/library/ff660871(v=pandp.20).aspx - 傍受の流れを示す良い図
  2. http://msdn.microsoft.com/en-us/library/ff647107.aspx - さまざまな傍受手法を示す過剰な詳細
于 2013-03-05T16:46:04.687 に答える