Cut down on repeated structure of Properties - c#

I have a class with many automatic string properties representing a customer. Briefly, something like this:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
This data comes from clients and many different file imports using a Nuget package. Those clients appear to be copying their data out of a database-generated system where we get literal "NULL" strings sometimes in some fields. I'd like to strip those out in an easy fashion with a little change to existing code as possible. I don't want errors thrown, I just want it to be null instead of "NULL" (not a validation failure for Address2, but is for LastName).
Because there are many imports and I'm using a library off Nuget without the source, I can't really catch the data coming in. All of it ends up in a pretty small number of classes before we process it, so this seems like the place to do it. I list two fields here, but there are over a dozen, and it's not just one class. We also use ValueInjector a lot, so swapping out string for a custom class isn't really an option.
The best I can come up with is undoing the auto-properties and using a string extension method for the null check. That just seems like a whole lot of repeated bloat. Is there any way to define this action on a property and say do that every time without turning one line of code into thirteen dozens of times over?
public static class StringExtensions
{
public static string NullMeansNull(this string value)
{
if (value == "NULL")
return null;
else
return value;
}
}
public class Person
{
private string _FirstName;
public string FirstName
{
get
{
return this._FirstName.NullMeansNull();
}
set
{
this._FirstName = value;
}
}
private string _LastName;
public string LastName
{
get
{
return this._LastName.NullMeansNull();
}
set
{
this._LastName = value;
}
}
}
Note I'm not talking about code formatting. We have enough StyleCop and CodeAnalysis rules that keep things expanded similar to above, which is good when it's code you actually want to read.

I gave up trying not to touch each import. I just made a generic extension method I call after importing data that looks for any editable string property, checking for "NULL" or empty string and converting it to null.
public static T CleanNullishStrings<T>(this T obj) where T : class
{
foreach (System.Reflection.PropertyInfo property in obj.GetType().GetProperties())
{
if (property.PropertyType == typeof(string) && property.CanRead && property.CanWrite)
{
string value = (string)property.GetMethod.Invoke(obj, null);
value = string.IsNullOrEmpty(value) || value.ToUpper() == "NULL" ? null : value;
property.SetMethod.Invoke(obj, new object[] { value });
}
}
return obj;
}
Since it generically returns the object passed, I can use it in projections:
IEnumerable<Person> = personList.Select(p => p.CleanNullishStrings());

Related

Finding and updating object based on a type using reflection

I’m trying to check the values in a nested object and replace them if necessary. Using reflection I can iterate through all the nested objects and get the property types but I’m stuck retrieving the values and replacing the values. I threw together a simple example.
Say I have the following model:
public class Employee
{
#region Members
private string _FirstName;
private string _LastName;
private StreetAddress _EmployeeAddress;
#endregion
#region Properties
public string FirstName { get { return _FirstName; } set { value = _FirstName; } }
public string LastName { get { return _LastName; } set { value = _LastName; } }
public StreetAddress EmployeeAddress { get { return _EmployeeAddress; } set { value = _EmployeeAddress; } }
#endregion
}
public class StreetAddress
{
#region Members
private string _Street;
private string _City;
private string _State;
private string _Zip;
#endregion
#region Properties
public string Street { get { return _Street; } set { value = _Street; } }
public string City { get { return _City; } set { value = _City; } }
public string State { get { return _State; } set { value = _State; } }
public string Zip { get { return _Zip; } set { value = _Zip; } }
#endregion
}
In my scenario I need to update the Street in StreetAddress from “123 Main Street” to “999 Main Street” for any object that StreetAddress appears in. The StreetAddress object could appear in any level of any give object.
So let’s say I have Employee cast as an object and I’m using the following to iterate through the Employee object looking for the StreetAddress type.
private static void ReadPropertiesRecursive2(Type type)
{
foreach (PropertyInfo property in type.GetProperties())
{
if (property.PropertyType == typeof(StreetAddress))
{
Debug.WriteLine(property.Name);
Type StreetAddressType = property.GetType();
//Get the value of 'Street'
//Here is where I'm having trouble figuring out how to get the value
Debug.WriteLine(StreetAddressType.GetProperty("Street").GetValue(StreetAddressType, null));
//The above throws the Exception: 'System.Reflection.TargetException'
//Check the value of 'Street'
//Replace the value of 'Street'
}
if (property.PropertyType.IsClass)
{
ReadPropertiesRecursive2(property.PropertyType);
}
}
}
Usage:
ReadPropertiesRecursive2(Employee.GetType());
I'm not sure what I'm missing in the syntax to use the 1) return the value of and 2) update the value if necessary. If you could point me in right direction, that would be awesome or if there is a better method I'd be interested to know about it. Thanks in advance!
Your biggest problem is that GetValue needs an actual object to get the value of. The PropertyInfo and for that matter, the Type is just metadata. In other words, a valid use of GetValue looks like:
Employee emp = new Employee();
PropertyInfo addressProp = typeof(Employee).GetProperty("StreetAddress");
string address = addressProp.GetValue(emp);
(Passing null tries to get it off the static "instance" for what its worth)
Refactor your code to get and set off of the actual instance and you should be fine.
If you could point me in right direction, that would be awesome or if there is a better method I'd be interested to know about it.
This answer falls more into the 'pointing in the right direction' category.
It appears that you want to update the street address on various entities which may contain an instance of StreetAddress somewhere in their structure, perhaps nested several levels deep.
The fundamental problem with this is that our code should be written to interact with specific properties of specific classes. We need to know which property we want to update and update that property, not just update any property that looks like it might be the right one because it's of a certain type.
Consider this example:
public class Employee
{
public StreetAddress Address {get;set;}
public EmergencyContact EmergencyContact {get;set;}
}
public class EmergencyContact
{
public StreetAddress Address {get;set;}
}
If you update an address the "normal" way:
employee.StreetAddress = updatedAddress;
or
employee.EmergencyContact.StreetAddress = updatedAddress;
then you're fine.
But if you do something like this:
UpdateStreetAddress(object something, "123 Maple St.")
...and then it goes looking for every StreetAddress, it's going to update every StreetAddress anywhere in that object. It will set both the employee's address and the employee's emergency contact's address.
It's not worth it trying to write a "one-size-fits-all" method that does this for every class. It's much better to just write code that updates exactly what you need to update. It's okay if it's a little bit more code (although it probably won't be.) You'll get that time back by not dealing with defects, unexpected side effects, and future developers not having to figure out what's happening.
Your problem here is that you are feeding in a type of object, but not the object itself.
When you provide the argument as
ReadPropertiesRecursive2(Employee.GetType());
You are not providing the Employee object itself, instead you are providing the 'type' of object.
So when you ask it to read the value of those properties, it is going to say 'Read this property or field on what object?'
StreetAddressType.GetProperty("Street").GetValue(StreetAddressType, null);
The null above, needs to be the actual object you are processing.
Change your method signature to:
private static void ReadPropertiesRecursive2(Type type, object obj)
Then feed your actual object that holds the data in as the second argument.
You might then be able to perform:
StreetAddressType.GetProperty("Street").GetValue(StreetAddressType, obj);
As now you will be telling it to read the 'Street' field on the obj object.

Property never null c#

When refactoring code, I come up with instances like the following
private string _property = string.Empty;
public string Property
{
set { _property = value ?? string.Empty); }
}
Later on in a method I see the following:
if (_property != null)
{
//...
}
Assuming that _property is only set by the setter of Property, is this code redundant?
I.e is there any way, through reflection wizardry or other methods that _property can ever be null?
Assuming that _property is only set by the setter of Property, is this
code redundant?
Exactly, it is redundant. This is the actual purpose of Properties. We shouldn't access the fields of a class directly. We should access them using a Property. So in the corresponding setter, we can embed any logic and we can rest assure that each time we try to set a value this logic would be verified once more.This argument holds even for the methods of a class. In a method we must use the properties and not the actual fields. Furthermore, when we want to read the value of a field, we should make use of the corresponding getter.
In general, properties enhances the concept of encapsulation, which is one of the pillars of object oriented programming OOP.
Many times there isn't any logic that should be applied when we want to set a value. Take for instance the following example:
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
We have declared a class for representing a Customer. A Customer object should have three properties an Id, a FirstName and a LastName.
An immediate question, when someones read this class is why should someone make use of properties here?
The answer is again the same, they provide a mechanism of encapsulation. But let's consider how can this help us in the long run. Let's say that one day someone decides that the first name of a customer should be a string of length less than 20. If the above class had been declared as below:
public class Customer
{
public int Id;
public string FirstName;
public string LastName;
}
then we should check for the length of FirstName in each instance we had created ! Otherwise, if we had picked the declaration with the properties, we could just easily make use of Data Annotations
public class Customer
{
public int Id { get; set; }
[StringLength(20)]
public string FirstName { get; set; }
public string LastName { get; set; }
}
and that's it. Another approach it could be the following:
public class Customer
{
public int Id { get; set; }
private string firstName;
public string FirstName
{
get { return firstName }
set
{
if(value!=null && value.length<20)
{
firstName = value;
}
else
{
throw new ArgumentException("The first name must have at maxium 20 characters", "value");
}
}
}
public string LastName { get; set; }
}
Consider both of the above approaches with having to revisit all your codebase and make this check. It's crystal clear that properties win.
Yes, it is possible through reflection. Nevertheless, I wouldn't worry about reflection -- people using reflection to defeat the design of your class is not something I worry about.
There is, however, something I do worry about: the phrase "Assuming that _property is only set by the setter of Property" is key. You are preventing users of your class from setting property to null.
You do not prevent, however, yourself or some other maintainer of your class from forgetting to only use the property INSIDE your class. In fact, your example has some one checking the field from inside the class rather than the property itself.... which means that, within your class, access comes from both the field and the property.
In most cases (where the problem could only come from inside the class) I would use an assertion and assert the field is not null.
If I really, really, really wanted to make sure that it wasn't null (barring reflection or people hell-bent on breaking things), you could try something like this:
internal class Program
{
static void Main()
{
string example = "Spencer the Cat";
UsesNeverNull neverNullUser = new UsesNeverNull(example);
Console.WriteLine(neverNullUser.TheString);
neverNullUser.TheString = null;
Debug.Assert(neverNullUser.TheString != null);
Console.WriteLine(neverNullUser.TheString);
neverNullUser.TheString = "Maximus the Bird";
Console.WriteLine(neverNullUser.TheString);
}
}
public class UsesNeverNull
{
public string TheString
{
get { return _stringValue.Value; }
set { _stringValue.Value = value; }
}
public UsesNeverNull(string s)
{
TheString = s;
}
private readonly NeverNull<string> _stringValue = new NeverNull<string>(string.Empty, str => str ?? string.Empty);
}
public class NeverNull<T> where T : class
{
public NeverNull(T initialValue, Func<T, T> nullProtector)
{
if (nullProtector == null)
{
var ex = new ArgumentNullException(nameof(nullProtector));
throw ex;
}
_value = nullProtector(initialValue);
_nullProtector = nullProtector;
}
public T Value
{
get { return _nullProtector(_value); }
set { _value = _nullProtector(value); }
}
private T _value;
private readonly Func<T, T> _nullProtector;
}
It is basically redundant. However, if it were mission critical or if for some reason it caused terrible side effects, it could remain. It is hard to tell, but part of your question was "can reflection change this value to null" to which the answer is yes and can be seen here in this linqpad demo
void Main()
{
var test = new Test();
test.Property = "5";
Console.WriteLine(test.Property);//5
FieldInfo fieldInfo = test.GetType().GetField("_property",BindingFlags.NonPublic | BindingFlags.Instance);
fieldInfo.SetValue(test, null);
Console.WriteLine(test.Property);//null
}
public class Test
{
private string _property = string.Empty;
public string Property
{
get { return _property; }
set { _property = value ?? string.Empty; }
}
}
I know this question is old, but look, I needed that one of my string properties never came up in null.
So I did this, and It worked for me
public string Operation { get; set; } = string.Empty;
In this way the default value is a string empty, but never null.

How can I efficiently design create / update methods, which need to create/update properties of different types?

I know, the question is long winded and probably difficult to understand, but hopefully someone has clicked on it and I can now explain in more detail what my issue is.
I have a Create method that is used to create an object called 'opportunity'. An opportunity has many different properties that need setting, but to make it simple I will use 'Title', 'Location', and 'StartDate'.
I also have an Update method that does something very similar and with regards to the properties listed it will set them in an identical way. However, as a side note I need 2 separate methods as they do differ.
Both methods take another object called an 'Entity' as a parameter, which is used to set the values for the 'opportunity'.
So, now to my issue. I was thinking the best approach is to have 1 method that does all of the property setting, which both methods use. I would pass a list of tuples to this method that contained 1.) the opportunity property name to be set, and 2.) the entity property value to set it to. However, to do this I would presumably need a tuple like string, object as the entity property value could be 1 of 5 types. Presumably this would cause boxing (and therefore is expensive). In addition to this I would be using the type to decide how to update the given opportunity property, so something like:
if (PropType == typeof(string))
{
//Do something
}
else if (PropType == typeof(Picklist))
{
//Do something else
}
else if (PropType == typeof(DateTime))
{
//Do something else
}
My question is, is this an efficient way of doing it? The 2 main reasons behind it for me are that it seems there is a lot of duplicate code between the create method and the update method as well as within each method with things like if(entity.prop.value != null) opp.prop.value = entity.prop.value. The second reason is that this way is easier to unit test. I can create a test for each opportunity property to be set and pass it into my new method as list of tuples and return if they've been created / updated correctly.
I considered a list of KeyValuePairs but I may need to add additional bits of info to the list so went with tuple. In addition, I think tuples are less expensive to pass to other methods (although more expensive to assign?).
I'm sure that despite my best efforts this still isn't clear, so any questions please ask.
EDIT
To give more clarity, there is an update method already in place (though I'm thinking of rewriting it) that has a lot of the same code in it to set the opportunity properties like this:
if(entity.Title.Value != null) opp.name = entity.Title.Value;
else throw new Exception("Title not specified");
if(entity.Town.Value != null) opp.town = entity.Town.Value;
else throw new Exception("Town not specified");
This is done for all string properties. My current view is I don't think I should need to duplicate this for all properties but rather have something that says:
//newOpp is passed in as the new opportunity
//Fields refers to a tuple passed in as object, string
//Item1 = entity field value
//Item2 = newOpp property name
PropertyInfo[] OppProps = newOpp.GetType().GetProperties();
PropertyInfo prop;
foreach (var record in Fields)
{
prop = OppProps.FirstOrDefault(x => x.Name == record.Item2);
if(record.Item1 != null && prop != null)
{
Type PropType = prop.GetType();
if (PropType == typeof(string))
{
prop.SetValue(newOpp, record.Item1, null);
}
//Extend to include other types used e.g. DateTime etc.
}
}
Because code says more then a few comment lines i made an example to illustrate what i mean.
public class Opportunity
{
public string Title { get; set; }
public string Location { get; set; }
public DateTime StartDate { get; set; }
}
public class OpportunityDto
{
public string Title { get; set; }
public string Location { get; set; }
[IgnoreMap]
public DateTime StartDate { get; set; }
}
public class Saver
{
public void CreateOpportunity(OpportunityDto dto)
{
var newOpportunity = new Opportunity();//You'll need some database logic here
MapProperties(dto, newOpportunity);
//Add save/create logic
}
public void UpdateOpportunity(OpportunityDto dto)
{
var existingUpportunity = new Opportunity();//you'll need some database query logic here
MapProperties(dto, existingUpportunity);
//Add save/update logic
}
public void MapProperties(OpportunityDto dto, Opportunity target)
{
Mapper.CreateMap<OpportunityDto, Opportunity>()
.ForAllMembers(opt => opt.Condition(srs => !srs.IsSourceValueNull));
Mapper.Map<OpportunityDto, Opportunity>(dto, target);
target.Startdate = dto.StartDate;//Insert more logic & mumbo jumbo here
//Or manually :
//target.Title = dto.Title;
//target.Location = dto.Location;
//target.StartDate = dto.StartDate;
}
}

How to create an array of the same properties?

So pretty much, what I'm trying to do is create a properties grid. It will hold things like input 0-5 or like output 1-64, which will have sub-properties like name, id, etc. Right now my code is very straight forward, and I initialize each one individually. That caused a problem when I wanted to save them to a text file and realized that doing it that way will cause walls of code. Instead of just being able to do a for loop, I would have to grab each one individually to write to the text file. I was wondering if there was a better approach to doing this with an array or list.
Here is what I have right now:
[CategoryAttribute("Input 0"), DescriptionAttribute("Name of Input 0"), DisplayName("Input 0: Name")]
public string IName_0
{
get {return _Iname[0];}
set {_Iname[0] = value;}
}
[CategoryAttribute("Input 0"), DescriptionAttribute("ID of Input 0"), DisplayName("Input 0: ID")]
public int IID_0
{
get { return _IID[0]; }
set { if ((64 > value) && (value >= 0)) _IID[0] = value; }
}
[CategoryAttribute("Input 1"), DescriptionAttribute("Name of Input 1"), DisplayName("Input 1: Name")]
public string IName_1
{
get { return _Iname[1]; }
set { _Iname[1] = value; }
}
[CategoryAttribute("Input 1"), DescriptionAttribute("ID of Input 1"), DisplayName("Input 1: ID")]
public int IID_1
{
get { return _IID[1]; }
set { if ((64 > value) && (value >= 0)) _IID[1] = value; }
It goes on like that for each input. I have been looking everywhere, and I can't find a good fix.
First you have to realize that containing your properties in a collection will cause them to be grouped together under it, when displayed on your PropertyGrid.
Therefore, having a collection of strings and another of ints will break your current structure, of:
Having pairs of properties (name and ID) grouped together;
Having all the properties on the root level of the property grid.
Having said that, you could solve issue #1 by making #2 a bit worse.
create two classes:
MyClass - containing a Name and IID properties.
MyClassCollection - a container class (most likely using an underlying List).
To mitigate issue #2, you can add code to expand all nodes at initialization as shown here.
If you try this, you will notice that the "containers" (MyClassCollection and MyClass) will have some undesired decription text appearing next to them when displayed.
This is where this article comes in handy.
Your property would then be:
[DisplayName("Some info here"),
DescriptionAttribute("Some more descriptive info here...")]
virtual public MyClassCollection MyData { get; set; }
and your class definitions would be along the lines of:
public class MyClass
{
public string Name
{
get { return _name; }
set { _name = value; }
}
public int IID
{
get { return _iid; }
set { if ((64 > value) && (value >= 0)) _iid = value; }
}
private string _name;
private int _iid;
}
public class MyClassCollection : CollectionBase
{
// See the article for code for the overrides (for CollectionBase) and implementation (for ICustomTypeDescriptor)
}
If you look at the article mentioned above, regarding the tweaking of the display text of the container classes, you'll have to make some adjustments to the classes above.

Objects Retrieved from List<T> Appear to Be Copies, Not References

In my code, I have a class that maintains a number of lists. We'll focus on one of them for the moment, since it's the one that highlighted the problem.
internal List<Badge> Badges { get; private set; }
In the code, I add Badge instances to this list when an XML document is parsed. Later, I want to update the individual instances in the list so I can have the data written back out to XML. Because of the way the data's XML structure differs from the original file structure, there's some hocus-pocus involved, but that's largely mapped out. The surprise came when I attempted to update an item in the List<Badge>.
Specifically, the problematic code is here:
// Get the current badge from the loaded XML data, so we can update it.
var currentBadge = this.GameData.GetCurrentBadge();
I always get a valid badge back. The surprise, as I've come to find out, is that this simple test always fails:
var result = this.GameData.Badges.IndexOf(currentBadge);
result always evaluates to -1, indicating that the object doesn't exist in the collection. (EDIT: Updating the properties on currentBadge has no effect whatsoever on the contents of the matching item in this.GameData.Badges.) Which leads me to conclude that I'm getting a copy of my object back, and not a reference, as I would have expected.
For the inquisitive, the code to retrieve badges from the GameData class is included below. I have a sneaking suspicion that this is a documented behavior of generic lists, and that this is the first time I've stumbled across it. If so, I'm in for a very rude awakening. If it's not, I'd really like to know why my objects are coming back "disconnected" from their originals.
private Badge GetCurrentBadge()
{
var badgeItem = GetCurrentBadgeItem();
if (badgeItem != null)
{
return this.GameData.GetBadgeByText(badgeItem.Text);
}
return null;
}
private MenuOption GetCurrentBadgeItem()
{
if (!(this.currentItem is MenuOption &&
(this.currentItem as MenuOption).IsLocked))
{
return null;
}
MenuOption result = null;
var children = this.currentMenu.Children;
for (var n = children.Count - 1; n >= 0; n--)
{
var child = children[n] as MenuOption;
if (child == null || !child.IsLocked)
{
break;
}
if (!child.Text.StartsWith(" "))
{
result = child;
break;
}
}
return result;
}
UPDATE: Per request, GetBadgeByText, which comes from the GameData class.
internal Badge GetBadgeByText(string badgeText)
{
foreach (var badge in Badges)
{
if (badge.Text.ToLower() == badgeText.ToLower())
{
return badge;
}
}
return null;
// var b = (from l in Badges
// where l.Text.ToLower().StartsWith(badgeText.ToLower())
// select l).FirstOrDefault();
//return b;
}
As you can see, I've tried it both with and without Linq, just to eliminate that as the culprit. Changing the implementation had no noticable effect.
And for the record, all the objects in this application are CLASSES. No structs anywhere.
UPDATE #2: The Badge class.
internal class Badge
: GameDataItem
{
public Badge()
: base()
{
}
public string AuthId { get; set; }
public string Category { get; set; }
public string Description { get; set; }
public bool IsAccoladePower { get; set; }
public string RequiredBadges { get; set; }
public override string ToString()
{
return Text;
}
internal string ToXml()
{
var template = "<Badge value=\"{0}\" title=\"{1}\" category=\"{2}\" authid=\"{3}\" requires=\"{4}\" accolade=\"{5}\" description=\"{6}\" />";
return string.Format(template,
this.Value,
this.Text,
this.Category,
this.AuthId,
this.RequiredBadges,
this.IsAccoladePower,
this.Description);
}
}
And just in case someone asks for it, the base class:
internal class GameDataItem
{
private string _text;
public string Text
{
get
{
return this._text;
}
set
{
this._text = value.Replace("<", "<")
.Replace(">", ">")
.Replace("&", "&");
}
}
public string Value { get; set; }
public override string ToString()
{
return Text + "=\"" + Value + "\"";
}
}
Looks to me like this has something to do with MenuOption's implementation of Equals(object). The IndexOf() method of the List<> will use Equals(object) when deciding what to return.
Either:
You are putting a copy of the object in the list. (List<T> does not clone objects or do any other sort of trickery.)
Badge is a struct, not a class, which means that you don't actually hold references to it since it would be a value type.
There's some copying going on elsewhere in code you haven't pasted.
A generic List<T> does not copy objects. You add references to it, and the same references comes out - so there must be another problem in the code.
How is GetBadgeFromText implemented ? Does it read directly from the Badges List ?
Is this a web app ? If yes, does your List live between requests, or is it deserialized and serialized on each request (this could also be the problem).

Categories

Resources