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?
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");
}
}
So it turns into this:
private string _MyValN;
public string MyValN {
get {
return _MyValN;
}
set : FilterSetter {
_MyValN = value;
OnPropertyChanged("MyValN");
}
}
The main difference between making a field public vs. exposing it through getters/setters is holding control over the property. If you make a field public, it means you provide direct access to the caller. Then, the caller can do anything with your field, either knowingly or unknowingly.
The get method returns the value of the variable name . The set method assigns a value to the name variable. The value keyword represents the value we assign to the property.
A get property accessor is used to return the property value, and a set property accessor is used to assign a new value. In C# 9 and later, an init property accessor is used to assign a new value only during object construction. These accessors can have different access levels.
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).
Concrete example:
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");
}
}
}
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; }
}
}
}
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 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.
You can create generic setter method and call that from each property setter:
private void Set<T>(ref T field, T value, string propertyName)
{
field = value;
Filter();
OnPropertyChanged(propertyName);
}
Then your properties look like:
public string SomeProperty
{
get { return this.someField; }
set
{
Set(ref this.someField, value, "SomeProperty");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With