Assign bool value to a property when name of that property is present in another array - c#

This is best I could make the question statement. Please be kind.
Here is the situation:
I have a string "InputValues" which contains values in comma seperated format:
chkAwareness1,chkAwareness2,chkAwareness6,chkAwareness9,chkAwareness13...
I need to fill an object with bool value if the name matches with what I have in above string variable.
example:
if InputValues contains "chkAwareness1" then "public bool chkAwareness1" should set to true, otherwise false.
public class SurveyCheckBox
{
public bool chkAwareness1 { get; set; }
public bool chkAwareness2 { get; set; }
public bool chkAwareness3 { get; set; }
public bool chkAwareness4 { get; set; }
public bool chkAwareness5 { get; set; }
public bool chkAwareness6 { get; set; }
public bool chkAwareness7 { get; set; }
.
.
.
}
public void createObjectSurveyCheckBox(string InputValues)
{
string[] ChkValues = InputValues.Split(',');
SurveyCheckBox surveyChkBoxObj = new SurveyCheckBox();
for (int i = 0; i < NumberOfPropertyInSurveyCheckBox ;i++ )
{
// typeof(SurveyCheckBox).GetProperties()[i].Name
}
}
I searched and I found GetProperties method through which I can get the name of property, but I am unable to figure out the logic.. how to search through the values and assign them to bool properties.
Please help.

You're very close. You just need to change your loop, really. The whole method should look like this:
public void CreateObjectSurveyCheckBox(string inputValues)
{
string[] chkValues = inputValues.Split(',');
SurveyCheckBox surveyChkBoxObj = new SurveyCheckBox();
foreach (string value in chkValues)
{
PropertyInfo propInfo = typeof(SurveyCheckBox).GetProperty(value);
if (propInfo != null)
propInfo.SetValue(surveyChkBoxObj, true);
}
}
P.S. You'll notice I took the liberty of changing your capitalization to something much more standard. If you use capitalization like you had, you're likely to get lynched.

I agree with Tim; I would not use something like this in production code.
public void createObjectSurveyCheckBox(string InputValues)
{
var instance = new SurveyCheckBox();
foreach (var property in typeof(SurveyCheckBox).GetProperties().Where(x => x.Name.Contains("chkAwareness")))
{
if (InputValues.Contains(property.Name))
property.SetValue(instance, true);
}
}

I would write the loop from the other direction, from 0 to MaxchkAwareness;
Sort the input first, before going into the loop.
You would also need an index to the next item in your input array (ChkValues), lets call that chkValueIndex;
If the next item in your input array, ChkValues[chkValueIndex], is "chkAwareness"+i.ToString()
then your property is true, and you increment your array pointer .
otherwise your property is false.
But I think you have to use reflection to set the properties in a loop like that, something like this:
Getting a property reference using reflection
I am sure there are better ways to restructure this and do it entirely different, but it sounds to me like you are trying to do the best you can with the system that was given you.

You can try this:
public static void createObjectSurveyCheckBox(string InputValues)
{
string[] ChkValues = InputValues.Split(',');
SurveyCheckBox surveyChkBoxObj = new SurveyCheckBox();
foreach (var prop in typeof(SurveyCheckBox).GetProperties())
{
if (ChkValues.Contains(prop.Name))
prop.SetValue(surveyChkBoxObj, true);
}
}

Related

Looping through a string array to create class variables of those strings

So I have this code in a .cs file called SchoolData that has a class and a list.
public static List<YearGroupsData> yearGroupsDataList = new List<YearGroupsData>();
public class YearGroupsData
{
public int id { get; set; }
public int year { get; set; }
public string groupName { get; set; }
public int subject { get; set; }
}
However, I'm trying to use a loop in another .cs script that does a web connection and gets the data from the website, I haven't included the connection info or some of the script for that as this isn't the part going wrong...
private IEnumerator ViewYearGroups()
{
//Some code for connection here
yield return viewYearGroups;
string yearGroupsDataString = viewYearGroups.text;
yearGroups = yearGroupsDataString.Split(';');
foreach (string yearGroup in yearGroups)
{
YearGroupsData yearGroupsData = new YearGroupsData()
{
id = Int32.Parse(GetDataValue(yearGroup, "Id:")),
year = Int32.Parse(GetDataValue(yearGroup, "Year:")),
groupName = GetDataValue(yearGroup, "GroupName:"),
subject = Int32.Parse(GetDataValue(yearGroup, "Subject:")),
};
SchoolData.yearGroupsDataList.Add(yearGroupsData);
}
}
The GetDataValue is the part that is messing up. It gives me ArgumentOutOfRangeException and I'm not sure why. It works if I'm not using it in a loop, I've tried a for loop as well and still the same, anyone know what's happening?
public string GetDataValue(string data, string index)
{
string value = data.Substring(data.IndexOf(index) + index.Length);
if (value.Contains("|"))
{
value = value.Remove(value.IndexOf("|"));
}
return value;
}
Add a try catch in your GetDataValue() method to help with debugging. If it works without the foreach loop, then my guess is one of the string objects you are iterating over is different than what you may be expecting.
https://msdn.microsoft.com/en-us/library/system.argumentoutofrangeexception(v=vs.110).aspx
try
{
string value = data.Substring(data.IndexOf(index) + index.Length);
}
catch (ArgumentOutOfRangeException e)
{
Console.WriteLine(e.Message);
}
Where I used the .Split to divide the string at each semicolon was the issue. The string I was splitting had a space after the last semicolon which was creating an empty index from that. I used
yearGroups = yearGroups.Take(yearGroups.Count() - 1).ToArray();
to remove the last index that was empty. The trycatch method helped me find this, thanks.
the ArgumentOutOfRangeException happen when the value of an argument is outside the allowable range of values as defined by the invoked method
try this:
string value = data.Substring(data.IndexOf(index) + index.Length - 1 );

Best way to group strings according to action

With "Best Way" I mean, maybe, without many If, clean code.
I have a function that receives as parameters (string currentVersion, string action)
and it should return a string versionToBe = "";
For action = "installOldVersion"
-------------if "currentVersion"----------------: -------------OldversionToInstall--------------
"windows10(pro)", "windows10(pro)(education)" : "windows81(pro)"
"windows10(enterprise)", "windows10(enterpise)(lstb)" : "windows81(enterprise)"
"windows7(home)", "windows7(home)(basic)", "windows7(basic)", "windows7": "windowsVista(starter)"
"windowsXP(starter)", "windowsXP(starter)(home)", "windowsXP(home)", "windowsXP": "windows2000(professional)"
"windowsNT(workstation)", "windowsNT": "windows95(sp1)"
For action = "installNewVersion"
-------------if "currentVersion"----------------: -------------NewVersionToInstall--------------
"windows81(pro)", "windows81(pro)(education)" : "windows10(pro)"
"windows81(enterprise)", "windows81(enterprise)(education)" : "windows10(enterprise)"
"windowsVista(starter)", "windowsVista(starter)(package)", "windowsVista(package)", "windowsVista": "windows7(home)"
"windowsVista(starter)", "windowsVista(starter)(praok)", "windowsVista(praok)", "windowsVista": "windowsXP(starter)"
"windows95(sp1)", "windows95(sp1)(versionE)", "windows95": "windowsNT(workstation)"
So,for example, everytime the string name comes like: "windows10(pro)" or "windows10(pro)(education)" it should return: "windows81(pro)".
I know this can get done with lots of if like:
if (version.Equals("windows10(pro)") || version.Equals("windows10(pro)(education)"))
{
versionToBe = "windows81(pro)";
}
and the same for the rest of them, anding with 10 If statements in Total.
But If there's a better way to do it, I'd want to know.
Another restriction, or other thing to consider:
if the action is "installOldVersion", versionToBe is OldversionToInstall,
and if the action is "installNewVersion", versionTobe would be NewVersionToInstall.
You could create a list of objects with CurrentVersion, Old Version and New Version and then extract the one you want from the list.
Example Instruction Class Definition
public class VersionInformation
{
public string CurrentVersion {get; set;}
public string NewVersion {get; set;}
public string OldVersion {get; set;}
}
then in your program, have a list of them, either hard coded or loaded from file or whatever datastore you want and do your version check as follows:
private List<VersionInformation> _versionInformation = //Load your list from wherever;
public void DoVersionCheck(string version)
{
var currentversionInfo = _versionInformation.Single(x=> x.CurrentVersion == version);
//Do Whatever you want with the upgrades and downgrades here based on whatever action you are doing
}
Set yourself up a dictionary and perform a lookup.
As an exercise for the reader:
You could drive the dictionary contents from some configuration or other...even from a database if you want.
You'd presumably want to set up your dictionary as a static and initialize it only once.
You'll want some handling for when there is no dictionary entry - you don't specify a default in your question.
Dictionary, string> ActionMatrix = new Dictionary, string>();
ActionMatrix.Add(Tuple.Create ("windows10(pro)", "installOldVersion"), "windows81(pro)");
ActionMatrix.Add(Tuple.Create ("windows10(pro)(education)", "installOldVersion"), "windows81(pro)");
ActionMatrix.Add(Tuple.Create ("windows10(enterprise)", "installOldVersion"), "windows81(enterprise)");
ActionMatrix.Add(Tuple.Create ("windows10(enterpise)(lstb)", "installOldVersion"), "windows81(enterprise)");
// etc
ActionMatrix.Add(Tuple.Create("windows81(pro)", "installNewVersion"), "windows10(pro)");
ActionMatrix.Add(Tuple.Create("windows81(pro)(education)", "installNewVersion"), "windows10(pro)");
ActionMatrix.Add(Tuple.Create("windows81(enterprise)", "installNewVersion"), "windows10(enterprise)");
ActionMatrix.Add(Tuple.Create("windows10(enterpise)(education)", "installNewVersion"), "windows10(enterprise)");
// etc
public string VersionToBe (string currentVersion, string action)
{
return ActionMatrix[Tuple.Create(currentVersion, action)];
}
A simple object with it's own list should do the trick and is visually better to follow.
public class VersionData
{
private static List<VersionData> VersionDatas { get; set; } = new List<VersionData>()
{
new VersionData( "OldversionToInstall", new [] {"windows10(pro)", "windows10(pro)(education)" }.ToList(), "windows81(pro)" ),
new VersionData( "OldversionToInstall", new [] {"windows10(enterprise)", "windows10(enterpise)(lstb)" }.ToList(), "windows81(enterprise)" )
};
public string Action { get; set; } = "";
public List<string> CurrentVersions { get; set; } = new List<string>();
public string Version { get; set; } = "";
public VersionData(string action, List<string> currentVersions, string version)
{
Action = action;
CurrentVersions = currentVersions;
Version = version;
}
public static string GetVersion(string action, string currentVersion)
{
return VersionDatas.FirstOrDefault(o => o.Action == action && o.CurrentVersions.Any(x => x == currentVersion)).Version;
}
}
and to call it's as simple as :
var oldVersion = VersionData.GetVersion("OldversionToInstall", "windows10(enterpise)(lstb)");

Accessing Property of Class in List<Class>

I see a lot of similar questions but none with a direct answer. I have a List<ClientEntry>. I want to access properties in ClientEntry. My code looks like this:
class ClientEntry
{
private string _clientName;
private string _clientEmail;
public void ClientEntry(string name, string email)
{
this._clientName = name;
this._clientEmail = email;
}
public string ClientName
{
get
{
return _clientName;
}
set
{
_clientName = value;
}
}
public string ClientEmail
{
get
{
return _clientEmail;
}
set
{
RegexUtilities Validator = new RegexUtilities();
if (Validator.IsValidEmail(value))
{
_clientEmail = value;
}
}
}
}
Later:
private List<ClientEntry> clientList;
I then add a bunch of ClientEntry's to the List.
How can I access the ClientName and ClientEmail properties for items in clientList? Also, how can I check for the existance of a certain ClientName or ClientEmail property within the List? Is this even possible with a list of objects? I know a dict would probably serve better, but I wanted to see if this could be done with a List and a class with properties.
You can use Linq to look for values inside of a list using Any()
Eg.
bool emailExists = clientList.Any(x=>x.ClientEmail == <email>);
To access values, you can use a index accessor if you know it, loop the collection, or use Where() to search it:
var email = clientList[index].ClientEmail
or
foreach (var client in clientList)
{
var email = client.ClientEmail
}
or
var email = clientList.Where(x=>x.ClientName == <clientName>).FirstOrDefault();
you can explore your list as below
foreach (ClientEntry client in clientList)
{
//client.ClientName
//client.ClientEmail
}
to find a particular record you can search it as
clientList.Where(p=> p.ClientEmail == "email#domain.com").FirstOrDefault();
To access a specific of item in the list, you input the index / using foreach
string name = clientList[index].ClientName;
foreach(var client in clientList)
{
name = client.ClientName; // access the item one by one
}
To check the existence of certain value of a property, use linq
bool isExist = clientList.Any(i => i.ClientName == "John");
Use Extension Methods !
Something like this, you can write unit test against the extension class easily and also it's straightforward to read.
public static class ClientEntriesExtension
{
public static bool ExistEmail(this IEnumerable<ClientEntry> entries, string targetEmail)
{
return entries.Any(x=>x.ClientEmail == targetEmail);
}
}
bool exist = clientList.ExistEmail(targetEmail)

c# What is wrong with my loop

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;
}
}

edit list inside foreach loop

I have an object with the following structure: (pseudocode)
class Client
{
- int ID
- int? ParentID
- string Name
- datetime CreateDate
- int ACClientID
- List <Client> Clients }
I want to loop through the whole nested structure using a recursive foreach, to set the ACClientID of ALL to a value.
I know that the enumerator in a foreach is immutable so the following doesn't work:
private static bool AssignToChildren(ref ATBusiness.Objects.Client client, int ACClientID)
{
client.ACClientID = ACClientID;
foreach (ATBusiness.Objects.Client child in client.Clients)
{
AssignToChildren(ref child, ACClientID);
}
}
What would be the most efficient way of achieving my goal?
PS: I will not be adding or removing from the structure, merely setting one attribute for every nested Client object.
[edit] I've looked at What is the best way to modify a list in a 'foreach' loop? but it does not provide me with the answer I need.
Since you never assign to the parameter client you need not pass it using ref.
Since you are not modifing the List<T> object themselves there is no reason you can't modify the ACCClientID property even during an enumeration. Its only when you try to tamper with the list membership that is behind the enumeration that you will get an exception.
private static bool AssignToChildren(ATBusiness.Objects.Client client, int ACClientID)
{
client.ACClientID = ACClientID;
foreach (ATBusiness.Objects.Client child in client.Clients)
{
AssignToChildren(child, ACClientID);
}
}
Can I suggest a specific property for this?
class Client
{
public Client()
{
Clients = new List<Client>();
}
public List<Client> Clients { get; private set; }
private int aCClientID;
public int ACClientID
{
get { return aCClientID; }
set { aCClientID = value; }
}
public int ACClientIDRecursive
{
get
{
return aCClientID;
}
set
{
aCClientID = value;
foreach (var c in Clients)
{
c.ACClientIDRecursive = value;
}
}
}
}
Try this:
private static bool AssignToChildren(ref ATBusiness.Objects.Client client, int ACClientID)
{
client.ACClientID = ACClientID;
for (int i = client.Clients.Count - 1; i >= 0; i--)
{
AssignToChildren(ref client.Clients[i], ACClientID);
}
}

Categories