I am having problems getting and setting a value because I have introduced a third aspect into my code.
Previously I would do this to get/set in the record:
public virtual string MyString { get; set;}
and then in my part:
public string MyString
{
get { return Record.MyString; }
set { Record.MyString = value; }
}
and NHibernate would save my values in the DB (obviously my other code is not presented here for the sake of brevity).
Now I am trying to do a checkbox with a list. I have this for a checkbox:
public class MyPart : ContentPart<MyPartRecord>
{
public MyPart()
{
MyList = Enum.GetValues(typeof(MyEnum))
.Cast<MyEnum>().Select(x =>
{
return new SelectListItem { Text = x.ToString().ToUpper(),
Value = ((int)x).ToString() };
}).ToList();
}
public IList<SelectListItem> MyList { get; set; }
private string myCheckBox;
// Record class contains the following commented code:
// public virtual string MyCheckBox { get; set;}
// Trying to do this now here in MyPart class:
public string MyCheckBox
{
get
{
if (!string.IsNullOrEmpty(myCheckBox))
return myCheckBox;
// Tried the following commented code to get value:
// Record.MyCheckBox = myCheckBox;
return string.Join(",", MyList.Where(x => x.Selected)
.Select(x => x.Value).ToArray());
}
set
{
myCheckBox = value;
// Tried the following commented code to set value:
// Record.MyCheckBox = myCheckBox;
}
}
}
I just don't know how to assign the values in this case (getting/setting myCheckBox into MyCheckBox. It's being saved in the DB as null.
Thanks in advance for any help.
It seems to me you'd be hiding the base virtual implementation of MyCheckBox.
I think instead you'd rather override the base:
public override String MyCheckBox
{
get
{
if (!string.IsNullOrEmpty(myCheckBox))
return myCheckBox;
// Tried the following commented code to get value:
// Record.MyCheckBox = myCheckBox;
return string.Join(",", MyList.Where(x => x.Selected)
.Select(x => x.Value).ToArray());
}
set
{
myCheckBox = value;
// Tried the following commented code to set value:
// Record.MyCheckBox = myCheckBox;
}
}
Thereby becoming the variable instead of obfuscating it?
I wound up just getting rid of the part and sticking with only a record - this allowed me to do the get and set in a view model, which worked out better (and was less confusing).
Related
I am trying to create a simple class. ColumnSort member is a list of items in comma delimited text "Car,Book,Food".
ColumnSortList creates a List
Car
Book
Food
C# and SonarQube is mentioning items like Error
Get: Add a way to break out of this property accessor's recursion.
Set: Use the 'value' parameter in this property set accessor declaration
How would I resolve these to make warnings/ errors (in SonarQube) go away? Open to making code more efficient also.
Note: columnSortList is purely supposed to be a read only computed field from ColumnSort string.
public class PageModel
{
public int Page { get; set; }
public int Limit { get; set; }
public string ColumnSort { get; set; }
public IEnumerable<string> columnSortList
{
get
{
return columnSortList;
}
set
{
if (ColumnSort == null)
{
columnSortList = null;
}
else
{
columnSortList = ColumnSort.Split(',')
.Select(x => x.Trim())
.Where(x => !string.IsNullOrWhiteSpace(x))
.AsEnumerable();
}
}
}
If columnSortList is intended to be purely read-only, computed from ColumnSort, then you should not have a set method at all. All the logic should go inside get like this:
public IEnumerable<string> columnSortList
{
get
{
if (ColumnSort == null)
{
return Enumerable.Empty<string>();
}
else
{
return ColumnSort.Split(',')
.Select(x => x.Trim())
.Where(x => !string.IsNullOrWhiteSpace(x))
.AsEnumerable();
}
}
}
Your getter is returning itself, which you can't do, and your setter is setting itself, which you also can't do. This here seems to be what you want:
public IEnumerable<string> columnSortList
{
get
{
if (ColumSort == null)
{
return new List<string>();
}
else
{
return ColumnSort.Split(',')
.Select(x => x.Trim())
.Where(x => !string.IsNullOrWhiteSpace(x))
.AsEnumerable();
}
}
}
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
I have a ChaseSelection class which i use in casting my dropdown list objects,
now i am trying to put the the values from the database as a default value in the drop down list, but it does not seem to work, can anyone help? I dont even think my loop runs. Here is my chaseselection class, and also put in the loop below: Thanks
public class ChaseSelectionItems
{
public string code { get; set; }
public string text { get; set; }
public ChaseSelectionItems(string code, string text)
{
this.code = code;
this.text = text;
}
public override string ToString()
{
return this.text;
}
}
foreach (ChaseSelectionItems items in drpdwnChaseSecSelection.Items)
{
if (items.code == _Row.xcs_View)
{
drpdwnChaseSecSelection.SelectedValue = items.text;
}
}
It is not entirely clear how you configured the listbox but most likely you did not configure ValueMember correctly. The following might fix that:
foreach (ChaseSelectionItems items in drpdwnChaseSecSelection.Items)
{
if (items.code == _Row.xcs_View)
{
// drpdwnChaseSecSelection.SelectedValue = items.text;
drpdwnChaseSecSelection.SelectedItem = items;
}
}
I've got something like this in my property/accessor method of a constructor for my program.
using System;
namespace BusinessTrips
{
public class Expense
{
private string paymentMethod;
public Expense()
{
}
public Expense(string pmtMthd)
{
paymentMethod = pmtMthd;
}
//This is where things get problematic
public string PaymentMethod
{
get
{
return paymentMethod;
}
set
{
if (string.IsNullOrWhiteSpace(" "))
paymentMethod = "~~unspecified~~";
else paymentMethod = value;
}
}
}
}
When a new attribute is entered, for PaymentMethod, which is null or a space, this clearly does not work. Any ideas?
do you perhaps just need to replace string.IsNullOrWhiteSpace(" ") with string.IsNullOrWhiteSpace(value) ?
From your posted code, you need to call:
this.PaymentMethod = pmtMthd;
instead of
paymentMethod = pmtMthd;
The capital p will use your property instead of the string directly. This is why it's a good idea to use this. when accessing class variables. In this case, it's the capital not the this. that makes the difference, but I'd get into the habit of using this.
Jean-Barnard Pellerin's answer is correct.
But here is the full code, which I tested in LinqPad to show that it works.
public class Foo {
private string _paymentMethod = "~~unspecified~~";
public string PaymentMethod
{
get
{
return _paymentMethod;
}
set
{
if (string.IsNullOrWhiteSpace(value))
_paymentMethod = "~~unspecified~~";
else _paymentMethod = value;
}
}
}
With a main of:
void Main()
{
var f = new Foo();
f.PaymentMethod = "";
Console.WriteLine(f.PaymentMethod);
f.PaymentMethod = " ";
Console.WriteLine(f.PaymentMethod);
f.PaymentMethod = "FooBar";
Console.WriteLine(f.PaymentMethod);
}
Output from console:
~~unspecified~~
~~unspecified~~
FooBar
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.