Adding a bool for each property - c#

I'm building a c# class that works with two different data sources. It will load a data source and take a configuration set from a function. Then I want to do several tasks on all properties within the object.
for example.
public String StreetAddress
{
get { return _streetAddress; }
set
{
if (value.Length <= 64)
_streetAddress = value;
else
_streetAddress = value.Substring(0, 1024).Trim();
}
}
public String City
{
get { return _city; }
set
{
if (value.Length <= 128)
_city = value;
else
_city = value.Substring(0, 128).Trim();
}
}
public String State
{
get { return _state; }
set
{
if (value.Length <= 128)
_state = value;
else
_state = value.Substring(0, 128).Trim();
}
}
So that holds the data from one side. I was hoping to be able to store and set a change flag on each property. So if we take State for example. If the person is moved from Texas to Illinois I want to set a bool within that property to note the change then be able to loop over all changes before saving the object to the DB. But I don't see any way to assign another state variable within that property. Is the best way to write another object on top of this to control it or is there another more creative way to store multiple strings within the one property?

If you'd like an OOP way of doing the thing, you can:
Define an interface and a class for holding your property, such as:
interface IPropertySlot
{
bool IsDirty { get; }
void ResetIsDirty();
object UntypedValue { get; }
}
class PropertySlot<T>:IPropertySlot
{
public T Value { get; private set; }
public bool SetValue(T value)
{
if (!Equals(_value, Value))
{
Value = value;
IsDirty = true;
return true;
}
return false;
}
public bool IsDirty { get; private set; }
public void ResetIsDirty()
{
IsDirty = false;
}
public object UntypedValue
{
get { return Value; }
}
}
Store your properties inside your class in a dictionary from String (for name of property) to IPropertySlot and get/set them through a pair of methods:
void SetProperty<T>(string name, T value)
{
IPropertySlot property;
if (!_properties.TryGetValue(name, out property))
{
property = new PropertySlot<T>();
_properties[name] = property;
}
((PropertySlot<T>)property) .SetValue(value);
}
T GetProperty<T>(string name)
{
IPropertySlot property;
if (!_properties.TryGetValue(name, out property))
{
property = new PropertySlot<T>();
_properties[name] = property;
}
return ((PropertySlot<T>)property).Value;
}
Finding the changed properties later is just a matter of going over the _properties.Values and finding which of them are IsDirty.
This approach also gives you a way to add more functionality to your properties in an OO manner (such as raising PropertyChanged/PropertyChanging events, mapping it to DB fields, etc.).

In such a situation I'd prefer an approach external to the Dto implementation.
Implement some unit that would take two instances of a class, and determine all the differences.
Map each property to compare:
static PropertyManager<Dto> manager = new PropertyManager<Dto>()
.Map(x => x.City)
.Map(x => x.StreetAddress);
Use two instances to compute difference:
var a = new Dto{ StreetAddress = "Foo", City = "Bar" };
var b = new Dto{ StreetAddress = "Foo", City = "Baz" };
var differences = manager.ComputeDifferences(a,b).ToList();
if( differences.Any() )
{
Console.WriteLine("Instances differ");
}
foreach (var diff in differences)
{
Console.WriteLine(diff);
}
This sample code prints out:
Instances differ
x.City
Here is a complete code example:
https://dotnetfiddle.net/4sNeoN

Related

Finding the items changed in Observable Collection

I have a class from a EF db context which I have displayed in a datagrid based on an ObservableCollection. The user can edit the the grid and this all displays fine.
However I now need to send the data back to the database. I do not want to send all the items in the collection to my save method, so can I find only the items that have been have change in the collection?
just as an idea (not professing this to be an ideal solution) i have run into a similar issue, looked around for potential solutions and none of those were exactly what i wanted.
i had to pass a collection to WPF DataGrid and it seemed to complain about using List, hence i turned to ObservableCollection
i did not want to work directly with the EF context for multiple reasons primarily because i wanted to grab items and pass them to intermediate transaction factory to be processed (business logic).
so decided to stick with ObservableCollection and instead make slight modification to the ViewModel since this i was free to do it.
my model ended up to look like this:
internal class databaseItemModel
{
int _id;
string _description;
decimal _price;
decimal _quantity;
decimal _cost;
bool _modified;
public databaseItemModel()
{
_modified = false;
}
public int id { get { return _id; } }
public bool modified { get { return _modified; } }
public string description { get { return _description; } set { _description = value; _modified = true; } }
public decimal price { get { return _price; } set { _price = value; _modified = true; } }
public decimal quantity { get { return _quantity; } set { _quantity = value; _modified = true; } }
public decimal cost { get { return _cost; } set { _cost = value; _modified = true; } }
public bool selected { get; set; }
public void setId(int _idvalue)
{
_id = _idvalue;
}
public decimal value
{
get { return price * quantity; }
}
public void setDescription(string _descr)
{
_description = _descr;
}
public void setPrice(decimal _pr)
{
_price = _pr;
}
public void setQuantity(decimal _qty)
{
_quantity = _qty;
}
public void setCost(decimal _cst)
{
_cost = _cst;
}
}
Basically, the plain idea behind it is that i would use functions to populate data rather than using properties direct and then pass the item to ObservableCollection which then would become the source for the DataGrid.ItemsSource
since DataGrid/ObservableCollection would work with properties - modified objects would be marked as modified and i would then be able to pick up the collection on exit and collect the modified items.
hope this is helpful.
You can use NotifyCollectionChangedAction to detect which items has been changed in the ObservableCollection
However, just Jens said, the best way would be let the EF handle it for you.
Cheers.
ObservableCollection<int> listOfObject = new ObservableCollection<int>() { 1, 2, 3, 4};
listOfObject.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(
delegate (object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
Console.WriteLine($"{e.NewItems[0]} just been added to the list at index = {e.NewStartingIndex}");
}
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)
{
Console.WriteLine($"Replace item {e.OldItems[0]} with {e.NewItems[0]}");
}
}
);
listOfObject.Add(1);
listOfObject[2] = 3;
listOfObject[3] = 1;
Output:
1 just been added to the list at index = 4
Replace item 3 with 3
Replace item 4 with 1

Two Definitions for 'This' Method

Is it possible to have 2 definitions for the this method? I want users to be able to do both of the following: string value = myBranch[stringKey]; and also Branch child = myBranch[stringKey].
Is this possible? And if not can you suggest how I could design my class to achieve the same outside interaction (ie, accessing a child branch or value easily)?
public class Branch {
public enum BranchType {TYPE_BRANCH, TYPE_LEAF}
private string key = null;
private string value = null;
private Branch parent = null;
private Dictionary <string, Branch> children = new Dictionary <string, Branch>();
// Is it possible to have 2 'this' definitions?
// Def 1:
public Branch this[string attribKey] {
get
{
if (this.children.ContainsKey(attribKey))
return this.children[attribKey];
return Branch.EmptyBranch;
}
set
{
children[attribKey] = value;
value.Parent = this;
this.Type = BranchType.TYPE_BRANCH;
}
}
// Def 1:
public string this[string attribKey] {
get
{
return value;
}
set
{
value = value;
}
}
public string Key {
get { return key; }
}
}
No, the one rule for overloads is that Overloads cannot differ only by return value. Since myBranch is probably a Dictionary, it doesn't make sense that it would sometimes return a string and sometimes a Branch. I would write two functions:
GetBranchByKey and GetStringByKey to solve the overload problem.

Reflection - object comparison & default values

I'm trying to compare two complex objects in C#, and produce a Dictionary containing the differences between the two.
If I have a class like so:
public class Product
{
public int Id {get; set;}
public bool IsWhatever {get; set;}
public string Something {get; set;}
public int SomeOtherId {get; set;}
}
And one instance, thus:
var p = new Product
{
Id = 1,
IsWhatever = false,
Something = "Pony",
SomeOtherId = 5
};
and another:
var newP = new Product
{
Id = 1,
IsWhatever = true
};
To get the differences between these, i'm doing stuff that includes this:
var oldProps = p.GetType().GetProperties();
var newProps = newP.GetType().GetProperties();
// snip
foreach(var newInfo in newProps)
{
var oldVal = oldInfo.GetValue(oldVersion, null);
var newVal = newInfo.GetValue(newVersion,null);
}
// snip - some ifs & thens & other stuff
and it's this line that's of interest
var newVal = newInfo.GetValue(newVersion,null);
Using the example objects above, this line would give me a default value of 0 for SomeOtherId (same story for bools & DateTimes & whathaveyou).
What i'm looking for is a way to have newProps include only the properties that are explicitly specified in the object, so in the above example, Id and IsWhatever. I've played about with BindingFlags to no avail.
Is this possible? Is there a cleaner/better way to do it, or a tool that's out there to save me the trouble?
Thanks.
There is no flag to tell if you a property was explicitly set. What you could do is declare your properties as nullable types and compare value to null.
If i understand you correctly, this is what microsoft did with the xml wrapping classes, generated with the xsd utility, where you had a XIsSpecified, or something like that, for each property X.
So this is what You can do as well - instead of public int ID{get;set;}, add a private member _id , or whatever you choose to call it, and a boolean property IDSpecified which will be set to true whenever Id's setter is called
I ended up fixing the issue without using reflection (or, not using it in this way at least).
It goes, more or less, like this:
public class Comparable
{
private IDictionary<string, object> _cache;
public Comparable()
{
_cache = new Dictionary<string, object>();
}
public IDictionary<string, object> Cache { get { return _cache; } }
protected void Add(string name, object val)
{
_cache.Add(name, val);
}
}
And the product implementation goes to this:
public class Product : Comparable
{
private int _id;
private bool _isWhatever;
private string _something;
private int _someOtherId;
public int Id {get { return _id; } set{ _id = value; Add("Id", value); } }
public bool IsWhatever { get { return _isWhatever; } set{ _isWhatever = value; Add("IsWhatever ", value); } }
public string Something {get { return _something; } set{ _something = value; Add("Something ", value); } }
public int SomeOtherId {get { return _someOtherId; } set{ _someOtherId = value; Add("SomeOtherId", value); } }
}
And the comparison is then pretty straightforward
var dic = new Dictionary<string, object>();
foreach(var obj in version1.Cache)
{
foreach(var newObj in version2.Cache)
{
//snip -- do stuff to check equality
dic.Add(....);
}
}
Doesn't hugely dirty the model, and works nicely.

how to implement autoimplemented properties in C# for setting a value

I am trying to use autoimplemented properties.
It shows me error
public OpenMode OpenFor
{
get;//must declare a body because it is not marked as abstract, partial or external. Why so
set
{
if (value == OpenMode.Add)
{
btnAddGuest.Text = "Save";
btnUpdatePreference.Visible = false;
dgvGuestInfo.ClearSelection();
}
else if (value == OpenMode.Update)
{
btnAddGuest.Text = "Update";
btnUpdatePreference.Visible = true;
}
}
}
You must implement both a getter and setter if you implement one of them. You can auto implement only both:
public OpenMode OpenFor
{
get;
set;
}
You may consider to use a backing field:
private OpenMode openFor;
public OpenMode OpenFor
{
get
{
return openFor;
}
set
{
openFor = value;
//...
}
}
autoimplementation works only for the simple usecase that set and get have no custom body
To use just get; you need to use just set; as well. In this case you'd have an implicit variable. When you declare a body for set, that doesn't work. Ask yourself the question; how can you get anything you can never set?
private OpenMode _openFor;
public OpenMode OpenFor
{
get{return _openFor;}
set{
_openFor = value;
SetOpenFor(value);
}
}
private void SetOpenFor(OpenMode mode)
{
if (mode== OpenMode.Add)
{
btnAddGuest.Text = "Save";
btnUpdatePreference.Visible = false;
dgvGuestInfo.ClearSelection();
}
else if (mode == OpenMode.Update)
{
btnAddGuest.Text = "Update";
btnUpdatePreference.Visible = true;
}
}
Also note that the auto-implemented properties also listen to access modifiers:
public string Foo { get; private set; }
Though you still need to define both.
In your example, it looks like you don't need the get. You aren't storing the value into a local field either, so it looks like your property should be a method.
Alternatively, your get could infer the value from the state of the buttons you are modifying in the set - but this is starting to get silly.

Replace a collection item using Linq

How do I find and replace a property using Linq in this specific scenario below:
public interface IPropertyBag { }
public class PropertyBag : IPropertyBag
{
public Property[] Properties { get; set; }
public Property this[string name]
{
get { return Properties.Where((e) => e.Name == name).Single(); }
//TODO: Just copying values... Find out how to find the index and replace the value
set { Properties.Where((e) => e.Name == name).Single().Value = value.Value; }
}
}
Thanks for helping out in advance.
Do not use LINQ because it will not improve the code because LINQ is designed to query collection and not to modify them. I suggest the following.
// Just realized that Array.IndexOf() is a static method unlike
// List.IndexOf() that is an instance method.
Int32 index = Array.IndexOf(this.Properties, name);
if (index != -1)
{
this.Properties[index] = value;
}
else
{
throw new ArgumentOutOfRangeException();
}
Why are Array.Sort() and Array.IndexOf() methods static?
Further I suggest not to use an array. Consider using IDictionary<String, Property>. This simplifies the code to the following.
this.Properties[name] = value;
Note that neither solution is thread safe.
An ad hoc LINQ solution - you see, you should not use it because the whole array will be replaced with a new one.
this.Properties = Enumerable.Union(
this.Properties.Where(p => p.Name != name),
Enumerable.Repeat(value, 1)).
ToArray();
[note: this answer was due to a misunderstanding of the question - see the comments on this answer. Apparently, I'm a little dense :(]
Is your 'Property' a class or a struct?
This test passes for me:
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
public interface IPropertyBag { }
public class PropertyBag : IPropertyBag
{
public Property[] Properties { get; set; }
public Property this[string name]
{
get { return Properties.Where((e) => e.Name == name).Single(); }
set { Properties.Where((e) => e.Name == name).Single().Value = value.Value; }
}
}
[TestMethod]
public void TestMethod1()
{
var pb = new PropertyBag() { Properties = new Property[] { new Property { Name = "X", Value = "Y" } } };
Assert.AreEqual("Y", pb["X"].Value);
pb["X"] = new Property { Name = "X", Value = "Z" };
Assert.AreEqual("Z", pb["X"].Value);
}
I have to wonder why the getter returns a 'Property' instead of whatever datatype .Value, but I'm still curious why you're seeing a different result than what I am.

Categories