您可以在属性变量中将方法作为默认 setter 操作的一部分吗? [英] Can you make a method part of the default setter action in a property variable?

查看:59
本文介绍了您可以在属性变量中将方法作为默认 setter 操作的一部分吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

If you have multiple properties that implement the same method in the setter, is there a way to make it part of the default setter?

如果我有多个在设置时调用 Filter() 的属性,有没有办法将其推送到基本设置器"中,这样​​我就不必拥有 Filter() 在每个 setter 中调用?

If I have multiple properties that call a Filter() when they are set, is there a way to push it into a "base setter" so that I don't have to have the Filter() call in every setter?

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_ 为前缀.拦截器代码在返回函数的途中执行一次,在返回的途中执行一次.在回来的路上,你可以让拦截器调用过滤器方法(当然假设它是在接口上定义的).

A different way of doing this is to use interception like that provided by the Unity framework. With interception your class implements an interface and you would tell the framework that everytime a method is called on classes implementing that interface, run these interceptors. Your interceptors code can look to see if the method being called is prefixed with set_. Interceptor code executes once on the way to the function and once on the way back. On the way back, you can then have the interceptor call the filter method (assuming it is defined on the interface of course).

具体例子:

使用 NuGet 将 Unity 和 Unity 扩展添加到您的项目

Use NuGet to add Unity and Unity extensions to your project

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();
        }
    }
}

运行此程序,您将看到拦截器实际上调用了过滤器方法(打印到控制台).

Running this you will see that the interceptor does in fact call the filter method (which prints to the console).

Unity 并不是唯一的依赖注入/拦截框架(谷歌 PostSharp).Unity 是我所熟悉的,所以这就是本示例使用的内容.

Unity is not the only dependency injection / interception framework out there (google PostSharp). Unity is the one i am familiar with so thats what this example uses.

  1. http://msdn.microsoft.com/en-us/library/ff660871(v=pandp.20).aspx - 描绘拦截流程的好图表
  2. http://msdn.microsoft.com/en-us/library/ff647107.aspx - 显示不同拦截技术的细节过度
  1. http://msdn.microsoft.com/en-us/library/ff660871(v=pandp.20).aspx - Good diagram depicting the flow of interception
  2. http://msdn.microsoft.com/en-us/library/ff647107.aspx - overkill of detail showing different interception techniques

这篇关于您可以在属性变量中将方法作为默认 setter 操作的一部分吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆