HasChanged method for c# model - c#

I am searching for a solution where i can ask a model if a property has changed. But i want to prevent to write own setter methods for all models and all their properties.
I want to use this to automatically generate a update queries based models and there changed properties. But if my model has a boolean property Test which is by default false, then i can't differentiate if the value is from the request payload or if it is the default value.
I already saw the INotifyPropertyChanged Implementation but there i have to write a setter for all properties too.
public class Main
{
public static void main()
{
var person = new Person();
Console.WriteLine(person.HasChanged("Firstname")); // false
Console.WriteLine(person.HasChanged("Lastname")); // false
Console.WriteLine(person.HasChanged("LikesChocolate")); // false
person.Firstname = "HisFirstname";
person.LikesChocolate = true;
Console.WriteLine(person.HasChanged("Firstname")); // true
Console.WriteLine(person.HasChanged("Lastname")); // false
Console.WriteLine(person.HasChanged("LikesChocolate")); // true
}
}
public class Person : BaseModel
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public bool LikesChocolate { get; set; }
}
public class BaseModel
{
public bool HasChanged(string propertyName)
{
// ...
}
}

I'd probably reuse the idea from WPF with their INotifyPropertyChanged pattern and simplify it a bit for the current needs. However, it resolves the question only partially, as you still need to write setters. But at least, you don't need to manage each property on its own.
So, the solution will be something like this:
void Main()
{
var person = new Person();
Console.WriteLine(person.HasChanged(nameof(Person.FirstName))); // false
Console.WriteLine(person.HasChanged(nameof(Person.LastName))); // false
Console.WriteLine(person.HasChanged(nameof(Person.LikesChocolate))); // false
person.FirstName = "HisFirstname";
person.LikesChocolate = true;
Console.WriteLine(person.HasChanged(nameof(Person.FirstName))); // true
Console.WriteLine(person.HasChanged(nameof(Person.LastName))); // false
Console.WriteLine(person.HasChanged(nameof(Person.LikesChocolate))); // true
}
public class Person : ChangeTrackable
{
private string _firstName;
private string _lastName;
private bool _likesChocolate;
public string FirstName
{
get { return _firstName; }
set { SetProperty(ref _firstName, value); }
}
public string LastName
{
get { return _lastName; }
set { SetProperty(ref _lastName, value); }
}
public bool LikesChocolate
{
get { return _likesChocolate; }
set { SetProperty(ref _likesChocolate, value); }
}
}
public class ChangeTrackable
{
private ConcurrentDictionary<string, bool> _changes =
new ConcurrentDictionary<string, bool>();
public bool HasChanged(string propertyName)
{
return _changes.TryGetValue(propertyName, out var isChanged)
? isChanged : false;
}
public void ResetChanges()
{
_changes.Clear();
}
protected void SetProperty<T>(
ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (!Equals(storage, value))
{
_changes[propertyName] = true;
}
}
}
The ChangeTrackable tracks if property was changed and does it without any reflection that guarantees high performance. Note, that with this implementation you need to call ResetChanges if you initialize property with some actual values after constructing the object. Drawback is that you need to write each property with its backing field and call SetProperty. On the other side, you decide what to track, that could be handy in the future in your application. Also we don't need to write property as strings (thanks to compile-time CallerMemberName and nameof) that simplifies refactorings.

INotifyPropertyChanged is the established practice for this type of requirement. Part of keeping your code maintainable is by keeping it predictable and by adopting best practices and patterns.
An alternative, which I wouldn't recommend, would be to use reflection to iterate over all of your properties and dynamically add a property changed event handler. This handler could then set a boolean flag which can be returned by your HasChanges method. Please refer to this for a staring point: AddEventHandler using reflection
I would recommend avoiding unnecessary complexity though and stick with PropertyChanged notifications in your setters.

As followup for my comment a proof of concept (online):
using System.Reflection;
public class HasChangedBase
{
private class PropertyState
{
public PropertyInfo Property {get;set;}
public Object Value {get;set;}
}
private Dictionary<string, PropertyState> propertyStore;
public void SaveState()
{
propertyStore = this
.GetType()
.GetProperties()
.ToDictionary(p=>p.Name, p=>new PropertyState{Property = p, Value = p.GetValue(this)});
}
public bool HasChanged(string propertyName)
{
return propertyStore != null
&& propertyStore.ContainsKey(propertyName)
&& propertyStore[propertyName].Value != propertyStore[propertyName].Property.GetValue(this);
}
}
public class POCO : HasChangedBase
{
public string Prop1 {get;set;}
public string Prop2 {get;set;}
}
var poco = new POCO();
poco.Prop1 = "a";
poco.Prop2 = "B";
poco.SaveState();
poco.Prop2 = "b";
poco.HasChanged("Prop1");
poco.HasChanged("Prop2");
Be aware, that reflection may reduce the performance of your application when used extensively.

Related

Implementing a safe access container

Assume I have some class that represents a container. That container holds some public properties with get and set modifiers.
What I want is to implement some mechanism that will enable access and disable access to these properties reference at runtime.
For example, when some boolean flag is true, you can access these properties. That means that:
SomeClass.Property1;
Will not generate an exception and will return the object.
However, when it is false, the above line of code will throw an exception.
It is of course possible to be done when using some boolean key, and checking it at the gateway to every property.
My question is, is it possible to implement such mechanism that will enfoce these limitations for all the properties in the class, without the need to assert these conditions within every access to these properties.
Thanks for helping.
It looks like null object pattern might helps.
Simple code that shows how it can be used in your case. Not exactly the same as you want but it doesn't need to assert conditions with every access to object's properties and methods.
Entities:
abstract class AbstractEntity
{
public abstract void DoSomething();
public abstract void DoSomethingElse();
public abstract int Property { get; set; }
}
class RealEntity : AbstractEntity
{
public override void DoSomething()
{
Console.WriteLine("Something");
}
public override void DoSomethingElse()
{
Console.WriteLine("Something else");
}
public override int Property { get; set; }
}
class NullEntity : AbstractEntity
{
public override void DoSomething()
{
// do nothing or throw exception
}
public override void DoSomethingElse()
{
// do nothing or throw exception
}
public override int Property
{
get { throw new Exception(); }
set { throw new Exception(); }
}
}
Simple example of AccessContainer:
class AccessContainer
{
private RealEntity _entity = new RealEntity();
private NullEntity _nullEntity = new NullEntity();
private bool _access = true;
public AbstractEntity Entity
{
get => _access ? (AbstractEntity) _entity : (AbstractEntity) _nullEntity;
}
public void OpenAccess()
{
_access = true;
}
public void DenyAccess()
{
_access = false;
}
}
Usage:
var container = new AccessContainer();
container.Entity.DoSomething(); // prints something
var prop = container.Entity.Property; // access to property
container.DenyAccess();
container.Entity.DoSomething(); // do nothing
container.OpenAccess();
container.Entity.DoSomething(); // prints something again
container.DenyAccess();
var prop2 = container.Entity.Property; // exception
What you are asking for doesn't natively exist, you're going to have to write some sort of wrapping functionality to test whether accessibility is granted.
public interface IAccessOwner {
bool Accessible { get; }
}
[DebuggerDisplay("Accessible: {Accessible,nq} - Value: {ToString()}")]
[DebuggerTypeProxy(typeof(RestrictedObject<>.DebuggerProxy))]
public class RestrictedObject<T> {
private readonly IAccessOwner _owner;
private T _value;
public RestrictedObject(IAccessOwner owner, T initialValue)
: this(owner) {
_value = initialValue;
}
public RestrictedObject(IAccessOwner owner) {
_owner = owner ?? throw new ArgumentNullException(nameof(owner));
}
public T Value {
get {
ThrowIfInaccessible();
return _value;
}
set {
ThrowIfInaccessible();
_value = value;
}
}
public bool Accessible => _owner.Accessible;
public override string ToString() {
if (!Accessible)
return "<Inaccessible>"; // ToString should never throw
if (_value is { } val)
return val.ToString();
return "<null>";
}
private void ThrowIfInaccessible() {
if(!Accessible)
throw new InvalidOperationException("Not accessible!");
}
// explicit operator to cast directly to value
public static explicit operator T(RestrictedObject<T> ro) {
ro.ThrowIfInaccessible();
return ro.Value;
}
private sealed class DebuggerProxy {
public bool Accessible { get; }
public T Value { get; }
public DebuggerProxy(RestrictedObject<T> ro) {
bool acc = Accessible = ro.Accessible;
if (acc)
Value = ro._value;
}
}
}
You can then use properties of this type in your class:
public class MyClass : IAccessOwner {
private readonly RestrictedObject<int> _prop1;
private readonly RestrictedObject<string> _prop2;
public MyClass(int someVal) {
_prop1 = new RestrictedObject<int>(this, someVal);
_prop2 = new RestrictedObject<string>(this);
Accessible = true;
}
public bool Accessible { get; private set; }
// you determine how you want to toggle the above property.
// Exposing it publicly defeats the purpose of all of this,
// but for demo purposes only:
public void DenyAccess() {
Accessible = false;
}
public void AllowAccess() {
Accessible = true;
}
// these properties will throw exceptions if the owner
// (this object) is not currently accessible.
public int Prop1 {
get => _prop1.Value;
set => _prop1.Value = value;
}
public string Prop2 {
get => _prop2.Value;
set => _prop2.Value = value;
}
// alternatively return the wrapper itself
// allowing you to control the accessibility
// even after returning the object
public RestrictedObject<string> AltProp2 => _prop2;
}
You would then use it like the following (obviously exceptions will halt the execution, handling has been elided):
var mc = new MyClass(3);
Console.WriteLine(mc.Prop1); // prints 3
Console.WriteLine(mc.Prop2); // prints null
var temp = mc.AltProp2; // use the wrapper directly
mc.Prop2 = "Hello";
Console.WriteLine(mc.Prop2); // prints Hello
Console.WriteLine(temp.Value); // prints Hello
Console.WriteLine((string)temp); // explicit operator, prints Hello
mc.DenyAccess();
mc.Prop1 = 33; // throws!
Console.WriteLine(mc.Prop1); // throws!
Console.WriteLine(mc.Prop2); // throws!
Console.WriteLine(temp.Value); // throws!
Console.WriteLine((string)temp); // explicit operator, throws!
Console.WriteLine(temp); // prints "<Inaccessible>"
mc.AllowAccess();
string temp3 = (string)temp; // "Hello", explicit operator works again
mc.Prop1 = 22; // as do our setters
mc.Prop2 = "Goodbye";
if (temp.Accessible) {
Console.WriteLine(temp); // "Goodbye"
}
The only thing that won't throw an exception is the override of ToString on the RestrictedObject type itself since you should never throw from ToString. Instead we just return <Inaccessible>.
We've also changed how the RestrictedObject<T> is displayed in a debugger via the DebuggerTypeProxyAttribute. If someone tries to inspect the object's properties they will see the Accessible property and only if true will the wrapped object's Value appear. Otherwise, default(T) will be displayed (null for reference types, 0 for integral types and false for bool). Furthermore, through use of the DebuggerDisplayAttribute we've customized the display of the collapsed version of our object such that it shows the Accessible property alongside our customized ToString.
Note that this still has the drawback that if someone retrieves the inner/wrapped object and accessibility has later been denied, they still have the object. There's nothing you are going to be able to do to really guard against that case. You must also realize (and accept) that anyone using reflection could alter or access the state of the object if they really wanted to.
I will also note that this violates normal C# practices, which typically dictate that properties should not throw exceptions. Microsoft's own guidelines say as much, though they use the term "Avoid" rather than "Do Not". The framework itself is guilty of violating this "rule". If you're going to violate the principle of least surprise, at the very least have the courtesy to document this behavior for consumers of your API.

GetSet in C# not being parsed

Relatively minor question about something I am missing here,
I am attempting to do a simple GetSet in C# to get the hang of the syntax but appear to have missed something as all that is printed is GetSet.Role and not the actual attributes being assigned.
Have I just worded something wrong? Apologies for the minor question but any help is appreciated.
namespace GetSet
{
class Program
{
static void Main(string[] args)
{
Role Mage = new Role("Staff", "Robes", "Magic affinity");
Role Warrior = new Role("Sword", "Platebody", "Strength");
Role Rogue = new Role("Needle", "Leather", "Cunning");
Console.WriteLine(Mage);
Console.WriteLine(Warrior);
Console.WriteLine(Rogue);
//stop the program from closing
Console.ReadLine();
}
}
}
and the following is my class:
namespace GetSet
{
class Role
{
//private variables
private string weapon;
private string armour;
private string passive;
//public structs
public Role(string aWeapon, string aArmour, string aPassive)
{
weapon = aWeapon;
armour = aArmour;
passive = aPassive;
}
//Getters and Setters for above private variables
public string Weapon
{
get { return weapon; }
set { weapon = value;}
}
public string Armour
{
get { return armour; }
set { armour = value;}
}
public string Passive
{
get { return passive; }
set { passive = value;}
}
}
}
Add a ToString() to your Role class and set it return whatever you want:
public override string ToString()
{
return $"Weapon: {weapon}, Armor: {armor}, Passive: {passive}";
}
You need to override the ToString method on the GetSet class.
Something like:
public override string ToString()
{
return $"{weapon}/{armour}/{passive}";
}
Update
You can simplyfy your Role class.
internal class Role
{
public Role(string weapon, string armour, string passive)
{
Weapon = weapon;
Armour = armour;
Passive = passive;
}
public string Weapon { get; }
public string Armour { get; }
public string Passive { get; }
public override string ToString()
{
return $"{Weapon}/{Armour}/{Passive}";
}
}
Re: vasily.sib's comment.
If you need to change the properties after object creation then simply change
public string Passive { get; }
to
public string Passive { get; set; }
As other answers lacks of getters/setters syntax examples, I will post my.
namespace GetSet
{
public class Role
{
// private backing field
private string _weapon;
// properties can have getters and setters, that contains some logic
public string Weapon
{
get { return _weapon; }
set { if (_weapon != vale) _weapon = value; }
}
// there is an auto-getters/setters
// in this case, backing field is handled by .Net CLR
public string Armour { get; set; }
// getters and setters may have different access level
// also, note property initializer '= "John";' - this will set property value
// to "John" right before constructor invocation
public string Name { get; private set; } = "John";
// properties also can be readonly, so they can be setted only in constructors
public string Passive { get; }
// public constructor
public Role(string passive)
{
Passive = passive;
}
public void ChangeName(string newName)
{
Name = newName; // setting property through private setter
}
// I believe, that this method shouldn't be used to represent object as string
// At least, I think, you should never relay on it's return value, BUT it ups to you
public overide string ToString() => Name;
}
}
Also, as you can see, I'm not setting publicly available properties (properties with public setters, Weapon and Armour) in consturctors, because I can initialize them along with constructing Role object, like this:
var mage = new Role("Magic affinity") { Weapon = "Staff", Armor = "Robes" };
mage.ChangeName("John, Doe");
As said before, I beleive that it is not relay on object itself, how it will look in string. I thinking so, because if you for some reasons need to represent same object as different strings in different places of your code - this will cause troubles. So instead of this:
// this will call .ToString() method
Console.WriteLine(mage);
// output: John, Doe
I suggest this:
// represent object as you need
Console.WriteLine($"{mage.Name} - walks in {mage.Armour}, beats with {mage.Weapon}");
// output: John, Doe - walks in Robes, beats with Staff

Too many calculated properties in my class

I have class which have too many related calculated properties.
I have currently kept all properties are read only.
some properties need long calculation and it is called again when its related properties are needed.
How can create this complex object .Also i want these properties should not be set from external code. I need show hide as i am binding properties for UI. Also i think order is also important.
My Class is something like
public string A
{
get
{
return complexMethod();
;
}
}
public string B
{
get
{
if (A == "value")
return "A";
else return "B";
;
}
}
public bool ShowHideA
{
get
{
return string.IsNullOrEmpty(A);
;
}
}
public bool ShowHideB
{
get
{
return string.IsNullOrEmpty(B);
;
}
}
public string complexMethod()
{
string value = "";
// calculation goes here
return value;
}
}
Thanks
You need to use Lazy type provided by .net:
Lazy<YourType> lazy = new Lazy<YourType>();
Make your properties internal to not be set from external code.
Well tall order isn't it?
One of the coolest things about extension methods is you can use types. This is perfect for writing external programs to calculate property values. Start like this...
public static class XMLibrary
{
public static MC CalculateValues(this MC myclass)
{
//for each property calculate the values here
if (myclass.Name == string.Empty) myclass.Name = "You must supply a name";
if (myclass.Next == 0) myclass.Next = 1;
//when done return the type
return myclass;
}
}
public class MC
{
public string Name { get; set; }
public int Next { get; set; }
}
public class SomeMainClass
{
public SomeMainClass()
{
var mc = new MC { Name = "test", Next = 0 };
var results = mc.CalculateValues();
}
}
There are many other ways to do class validation on a model, for example dataannotations comes to mind, or IValidatableObject works too. Keeping the validation separate from the class is a good idea.
//Complex properites are simple
public class MyComplextClass{
public List<MyThings> MyThings {get;set;}
public List<FileInfo> MyFiles {get;set;}
public List<DateTime> MyDates {get;set;}
}

C# Properties based on choice

I need a little help i am using a class and want to set the properties based on choice on type int,string and datetime here is my code that i wrote but as my constructor will be confused between public string paramValue and public int? paramValue what is the best way to set properties based on choice so only one property can be set a time.Thanks for any suggestion
public class PassData
{
private string _ParamName { get; set; }
private int? _ParamValueInt { get; set; }
private string _ParamValueString { get; set; }
private DateTime? _ParamValueDateTime { get; set; }
public string paramName
{
get { return _ParamName; }
set { _ParamName = value;}
}
public string paramValue
{
get { return _ParamValueString; }
set {_ParamValueString = value; }
}
public int? paramValue
{
get { return _ParamValueInt; }
set { _ParamValueInt = value; }
}
public PassData(string ParamName, int ParamValue)
{
paramName = ParamName;
paramValue = ParamValue;
}
public PassData(string ParamName, string ParamValue)
{
ParamName = ParamName;
ParamValueString = ParamValue;
}
public PassData(string ParamName, DateTime ParamValue)
{
ParamName = ParamName;
ParamValueDateTime = ParamValue;
}
}
Basically, you can't have multiple properties on an object that only differ by type. You have a few options.
1) Create a single property that can hold various types:
private Object _paramValue;
public Object ParamValue
{
get { return _paramValue; }
set {_paramValue= value; }
}
In your setter, you can throw an exception if the value is a type you don't like. You'd also have to upcast the result every time you called the getter, making this solution not ideal. If you want to go this route, I'd suggest making the property an interface, and defining various implementations for the types of data you need.
2) Create a generic class:
public class PassData<T>
{
private T _paramValue;
public T paramValue
{
get { return _paramValue; }
set {_paramValue= value; }
}
}
This has the disadvantage of not being able to change the type after the instance is created. It was unclear if this was a requirement for you.
I like this design as it provides for the possibility of making the constructor for this class private:
public class PassData<T>
{
private PassData(T value)
{
this._paramValue = value;
}
}
If you did this, you can create overloaded static methods to allow the creation of instances:
public static PassData<String> CreateValue(string value)
{
return new PassData<String>(value);
}
public static PassData<Int32> CreateValue(Int32 value)
{
return new PassData<Int32>(value);
}
That way, you can control what types can be created.
Not an answer (in the sense that it does not offer you a way to do what you're trying to do, as Mike Christensen's answer covers it). I just wanted to get more into why what you are trying to do is not working.
Your expectation for it to work is not unreasonable per se, the issue is that c# is not polymorphic on return values. I think some other languages are, C# is not.
i.e. while in c#, you can do:
public void test(int val) {}
public void test(string val) {}
// When you call `test` with either an int or a string,
// the compiler will know which one to call
you CAN'T do:
public int test() {return 1;}
public string test() {return "1";}
// does not compile. The compiler should look at the call
// site and see what you assign the result of "test()" to
// to decide. But there are various edge cases and it was decided
// to leave this out of the language
Now, the get on string paramValue is functionally equivalent to this scenario. You're trying to get the compiler to decide which paramValue to call based on the return value.

Design a mutable class that after it's consumed becomes immutable

Suppose that the scenario doesn't allow to implement an immutable type. Following that assumption, I'd like opinions / examples on how to properly design a type that after it's consumed, becomes immutable.
public class ObjectAConfig {
private int _valueB;
private string _valueA;
internal bool Consumed { get; set; }
public int ValueB {
get { return _valueB; }
set
{
if (Consumed) throw new InvalidOperationException();
_valueB = value;
}
}
public string ValueA {
get { return _valueA; }
set
{
if (Consumed) throw new InvalidOperationException();
_valueA = value;
}
}
}
When ObjectA consumes ObjectAConfig:
public ObjectA {
public ObjectA(ObjectAConfig config) {
_config = config;
_config.Consumed = true;
}
}
I'm not satisfied that this simply works, I'd like to know if there's a better pattern (excluded, as said, making ObjectAConfig immutable by design from begin).
For example:
can make sense define a monad like Once<T> that allow the wrapped value to be initialized only once?
can make sense define a type that returns the type itself changing a private field?
What you are implementing sometimes goes under the name "popsicle immutability" - i.e. you can freeze it. Your current approach will work - indeed I use that pattern myself in numerous places.
You can probably reduce some duplication via something like:
private void SetField<T>(ref T field, T value) {
if (Consumed) throw new InvalidOperationException();
field = value;
}
public int ValueB {
get { return _valueB; }
set { SetField(ref _valueB, value); }
}
public string ValueA {
get { return _valueA; }
set { SetField(ref _valueA, value); }
}
There is another related approach, though: a builder. For example, taking your existing class:
public interface IConfig
{
string ValueA { get; }
int ValueB { get; }
}
public class ObjectAConfig : IConfig
{
private class ImmutableConfig : IConfig {
private readonly string valueA;
private readonly int valueB;
public ImmutableConfig(string valueA, int valueB)
{
this.valueA = valueA;
this.valueB = valueB;
}
}
public IConfig Build()
{
return new ImmutableConfig(ValueA, ValueB);
}
... snip: implementation of ObjectAConfig
}
Here there is a truly immutable implementation of IConfig, and your original implementation. If you want the frozen version, call Build().

Categories

Resources