微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 你能把一个方法作为属性变量中默认的setter动作的一部分吗?

如果你有多个属性在setter中实现相同的方法,有没有办法让它成为认setter的一部分?

如果我有多个属性在设置时调用Filter(),是否有办法将其推入“基本setter”,这样我就不必在每个setter中调用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");
    }
}

解决方法

执行此操作的另一种方法是使用Unity框架提供的拦截.通过拦截,您的类实现了一个接口,您将告诉框架每次在实现该接口的类上调用方法时,运行这些拦截器.您的拦截代码可以查看被调用方法是否以set_为前缀.拦截代码在前往函数的路上执行一次,在返回途中执行一次.在回来的路上,你可以让拦截调用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();
        }
    }
}

运行它你会看到拦截器确实调用了filter方法(打印到控制台).

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显示不同拦截技术的细节过度

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐