Consider these properties,
double _temperature;
public double Temperature
{
get { return _temperature; }
set { _temperature = value; }
}
double _humidity;
public double Humidity
{
get { return _humidity; }
set { _humidity = value; }
}
bool _isRaining;
public bool IsRaining
{
get { return _isRaining; }
set { _isRaining = value; }
}
And now I want to make a list/collection/container of properties like this,
PropertyContainer.Add(Temperature); //Line1
PropertyContainer.Add(Humidity); //Line2
PropertyContainer.Add(IsRaining); //Line3
I want to make this such that later on I may be able to access the current values of properties using index, something like this,
object currentTemperature = PropertyContainer[0];
object currentHumidity = PropertyContainer[1];
object currentIsRaining = PropertyContainer[2];
But obviously, this is not going to work, since PropertyContainer[0] will return the old value - the value which Temperature had at the time of adding Temperature to the container (see the Line1 above).
Is there any solution to this problem? Basically I want to access current values of properties uniformly; the only thing that can change is, the index. The index however could be string as well.
PS: I don't want to use Reflection!
Well, you could use Lambdas:
List<Func<object>> PropertyAccessors = new List<Func<object>>();
PropertyAccessors.Add(() => this.Temperature);
PropertyAccessors.Add(() => this.Humidity);
PropertyAccessors.Add(() => this.IsRaining);
then you could to this:
object currentTemperature = PropertyAccessors[0]();
Related
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
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
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.
I was looking for a similar way to create an alias for something else like its possible in C using preprocessor (this question is a bit similar, couldn't find anything useful there).
This is the problem: I've got a method that receives an array, but each position of the array has a specific meaning, like they where different parameters with specific names. What I want to do is to make my code easier to read (and write) by using those specific names, but, on the other hand, I don't want to create another method call (like in example 1) nor assign the array positions to new variables (example 2), because the performance is critical.
Example 1:
void OriginalMethodSignature(Type[] values)
{
SimplifiedMethod(values[0], values[1], ... values[n]);
}
void SimplifiedMethod(Type specificName1, Type specificName2, ... Type specificNameN)
{
// simple implementation using specific names instead of values[n]
}
Example 2:
void OriginalMethodSignature(Type[] values)
{
Type specificName1 = values[0];
Type specificName2 = values[1];
...
Type specificNameN = values[n];
// simple implementation using specific names instead of values[n]
}
I cannot change the method signature because its used in a dellegate, the Type is fixed.
The next example is a bit better, but still not optimum:
void OriginalMethodSignature(Type[] values)
{
// implementation using values[specificName1] ... values [specificNameN]
}
const int specificName1 = 0;
const int specificName2 = 1;
...
const int specificNameN = n-1;
Is there any way to create an snippet for this purpose? If yes, how would it be?
There isn't any built in way to do what you wan't, because you shouldn't really be doing it at all. You should be using an object with properties instead of an array.
Anyway, you can make an object that encapsulates the array, so that the properties use the array as storage:
public class NamedObject {
private Type[] _values;
public NamedObject(Type[] values) {
_values = values;
}
public SpecificName1 { get { return _values[0]; } set { _values[0] = value; } }
public SpecificName2 { get { return _values[1]; } set { _values[1] = value; } }
public SpecificName3 { get { return _values[2]; } set { _values[2] = value; } }
public SpecificName4 { get { return _values[3]; } set { _values[3] = value; } }
public SpecificName5 { get { return _values[4]; } set { _values[4] = value; } }
public SpecificName6 { get { return _values[5]; } set { _values[5] = value; } }
}
Now you can use the object to access the array:
void OriginalMethodSignature(Type[] values) {
NamedObject obj = new NamedObject(values);
// get a value
Type x = obj.SpecificName4;
// set a value
obj.SpecificName2 = x;
}
Create a dedicated class or struct, and parse the array into it.
public class MyClassOfStuff
{
Type SpecificName1 {get;set;}
Type SpecificName2 {get;set;}
public static MyClassOfStuff Parse(Type[] value)
{
Type specificName1 = values[0];
Type specificName2 = values[1];
...
Type specificNameN = values[n];
}
}
void OriginalMethodSignature(Type[] values)
{
var mystuff = MyClassOfStuff.Parse(values);
}
In my Class i need to set one property value according to another:
public class Quantities
{
private int _quant;
public int Quant
{
get { return _quant; }
set
{
if (Unit == "K")
{
_quant = value / 1000;
}
else
{
_quant = value;
}
}
}
public string Unit { get; set; }
}
according to several tests i made it works fine but i still don't know if it's safe to do this.
is it possible that the Quant Property will be evaluated before the Unit Property or does the compiler (or JIT) knows that it should assign the Unit Property first?
This has nothing to do with the compiler or the JIT. Your code assigns the values. You need to know the order in which they should be assigned.
BTW: Your code exhibits temporal coupling. It would be better to make at least the Unit unchangeable by making the property readonly and by providing a constructor that requires the unit:
public class Quantities
{
private readonly string _unit;
private int _quant;
public Quantities(string unit)
{
if(unit == null) throw new ArgumentNullException("unit");
_unit = unit;
}
public int Quant
{
get { return _quant; }
set
{
if (Unit == "K")
{
_quant = value / 1000;
}
else
{
_quant = value;
}
}
}
public string Unit { get { return _unit; } }
}
This class now can't be used in an incorrect way.
For more points that can be improved with your class, please refer to Lasse's answer.
Code on the outside of this class must know about this dependency or you risk someone changing Unit without re-setting Quant:
var x = new Quantities(); // why no constructor for this?
x.Unit = "K";
x.Quant = 1700; // why int? this will now be 1, not 1.7
x.Unit = "M";
Personally I would make the class a struct, and make it immutable:
public struct Quantity
{
private readonly double _Value;
private readonly string _Unit;
public Quantity(double value, string unit)
{
_Value = value;
_Unit = unit;
}
public double Value
{
{
return _Value;
}
}
public double Unit
{
{
return _Unit;
}
}
}
Also note that I did not change the value at all, hence:
var x = new Quantity(1700, "K");
means 1700K, not 1.7K. I would refrain from doing such "automagical" interpretations of data. If you need to display the value with a different unit, I would instead build in a conversion system:
public Quantity ConvertToUnit(string newUnit)
{
var newValue = ... calculate value with new unit
return new Quantity(newValue, newUnit);
}
The class is not a good design. Do not do this.
Consider the following code:
Quantities q1 = new Quantities { Unit = "K", Quant = 1000};
Console.WriteLine(q1.Quant); // Prints 1
// Make a copy of q1
Quantities q2 = new Quantities{ Unit = q1.Unit, Quant = q1.Quant };
Console.WriteLine(q2.Quant); // Prints 0
You would expect that making a copy of the Quantities would work by doing a basic copy like the above. That it does not shows you how dangerous this kind of design is.
This is still a problem after making the changes in the accepted answer above
If you use the changes that Daniel suggested, you still have the nastyness associated with your property setter and getter not being commutative. Sure, you would be forced to pass the units into the constructor, but the object copy still won't work as the user might expect:
Quantities q1 = new Quantities("K"){ Quant = 1000};
Console.WriteLine(q1.Quant); // Prints 1
// Make a copy of q1
Quantities q2 = new Quantities(q1.Unit){ Quant = q1.Quant };
Console.WriteLine(q2.Quant); // STILL Prints 0