Is this bad practice? Or is it completely fine to do this
private readonly List<KeyValuePair<GameType, KeyValuePair<string, string>>> _tempStats = new List<KeyValuePair<GameType, KeyValuePair<string, string>>>();
GameType is an enumerator by the way.
I have data that I am downloading from a table that has a few different GameTypes with two strings associated with them. So it will parse the data and determines what GameType to assign it, and it finds the tables Key and it's Value. And it works, it stores the information and I am able to retrieve it with no problems, but it just seems like having a list of a KeyValuePair with a KeyValuePair isn't right, but maybe it is. Would using a tuple be a better approach?
My current usage of the list
private void ParseNodeText(string nText, GameType gmode)
{
_tempStats.Clear();
var reader = new StringReader(nText);
while((nText = reader.ReadLine()) != null)
{
nText = nText.Replace(" ", "");
if (nText == "")
{
continue;
}
string statType = Regex.Replace(nText, "[^A-Za-z]", "");
string statValue = Regex.Replace(nText, "[^0-9]", "");
// Console.WriteLine(gmode + " : Found line with Type of {0} and a value of {1}",statType,statValue);
_tempStats.Add(new KeyValuePair<GameType, KeyValuePair<string, string>>(gmode, new KeyValuePair<string, string>(statType, statValue)));
}
}
Your Solution is fine, but not that good readable.
You could do something like this:
private readonly List<GameStats> _tempStats = new List<GameStats>();
and GameStats is a own written simple Class:
public class GameStats
{
public GameType Type { get; set; }
public string StatType { get; set; }
public string StatValue { get; set; }
public GameStats(GameType gameType, string statType, string statValue)
{
this.Type = gameType;
this.StatType = statType;
this.StatValue = statValue;
}
}
and add it to your list like:
_tempStats.Add(new GameStats(gmode, statType, statValue));
i think, this looks good and will do it.
Related
I am trying to get the object value but I don't know how to do it. I'm new to C# and its giving me syntax error. I want to print it separately via the method "PrintSample" How can I just concatenate or append the whatData variable . Thank you.
PrintSample(getData, "name");
PrintSample(getData, "phone");
PrintSample(getData, "address");
//Reading the CSV file and put it in the object
string[] lines = File.ReadAllLines("sampleData.csv");
var list = new List<Sample>();
foreach (var line in lines)
{
var values = line.Split(',');
var sampleData = new Sample()
{
name = values[0],
phone = values[1],
address = values[2]
};
list.Add(sampleData);
}
public class Sample
{
public string name { get; set; }
public string phone { get; set; }
public string adress { get; set; }
}
//Method to call to print the Data
private static void PrintSample(Sample getData, string whatData)
{
//THis is where I'm having error, how can I just append the whatData to the x.?
Console.WriteLine( $"{getData. + whatData}");
}
In C# it's not possible to dynamically evaluate expression like
$"{getData. + whatData}"
As opposed to languages like JavaScript.
I'd suggest to use rather switch expression or Dictionary<string, string>
public void PrintData(Sample sample, string whatData)
{
var data = whatData switch
{
"name" => sample.name,
"phone" => sample.phone,
"address" => sample.address
_ => throw new ArgumentOutOfRangeException(nameof(whatData)),
};
Console.WriteLine(data);
}
I'm not sure what you are trying to achieve. Perhaps this will help you:
private static void PrintSample(Sample getData, string whatData)
{
var property = getData.GetType().GetProperty(whatData);
string value = (string)property?.GetValue(getData) ?? "";
Console.WriteLine($"{value}");
}
What PO really needs is
private static void PrintSamples(List<Sample> samples)
{
foreach (var sample in samples)
Console.WriteLine($"name : {sample.name} phone: {sample.phone} address: {sample.address} ");
}
and code
var list = new List<Sample>();
foreach (var line in lines)
{
......
}
PrintSamples(list);
it is radicolous to use
PrintSample(getData, "name");
instead of just
PrintSample(getData.name)
You can do this using reflection. However, it's known to be relatively slow.
public static void PrintSample(object getData, string whatData)
{
Console.WriteLine( $"{getData.GetType().GetProperty(whatData).GetValue(getData, null)}");
}
I have a string name given to me in a string.
Like this:
string myawesomestring = "hey";
string mystringname = "myawesomestring";
I need to get myawesomestring value but the myawesomestring can change.
I hope you get what I mean, if you don't comment I will fix it myself.
Something like this?
string mystringname += myawesomestring;
I understand that you want to read the value of a string by some kind of string value stored in another variable (which is dynamic). I don't think this can be achieved with just simple string data type, but you can do this by using some complex data types like dictionary or class or something similar.
First solution might be storing the data in a dictionary, but you have to make sure the keys are unique. E.g.
string mystringname1 = "MyAwesomeString1";
string mystringname2 = "MyAwesomeString2";
var awesomeStrings = new Dictionary<string, string>
{
{"MyAwesomeString1","hey1" },
{"MyAwesomeString2","hey2" }
};
string vaule1 = awesomeStrings[mystringname1];
string vaule2 = awesomeStrings[mystringname2];
If you have more attributes, then you can create a class and with the use of little bit of reflection, you can easily read the property values. E.g.
public class AwesomeString
{
public string MyAwesomeString1 { get; set; } = "hey1";
public string MyAwesomeString2 { get; set; } = "hey2";
}
class Program
{
static void Main(string[] args)
{
string mystringname1 = "MyAwesomeString1";
string mystringname2 = "MyAwesomeString2";
AwesomeString awesomeString = new AwesomeString();
string vaule1 = (string)awesomeString.GetType().GetProperty(mystringname1).GetValue(awesomeString);
string vaule2 = (string)awesomeString.GetType().GetProperty(mystringname2).GetValue(awesomeString);
/* ... */
}
}
I'm having trouble converting the following string array into a POCO object.
Given the following:
string files = [
"./Folder/file.ext",
"./Folder/file2.ext",
"./Folder/file3.ext",
"./Folder/nestedfolder/file.ext",
"./Folder2/file1.ext",
"./Folder2/file2.ext",
"./file1.ext",
"./file2.ext",
"./file3.ext",
];
I would like to convert it to something like:
public class HierarchicalSource{
public List<HierarchicalSource> Children = new List <HierarchicalSource> ();
public bool folder { get; set; }
public string FullPath;
public HierarchicalSourceSource(string path) {
this.FullPath = path;
}
}
Where HierarchicalSource is the root, and has a list of children
UPDATE:
I ended up changing the list to a dictionary. There must be a more efficient way to do this, but I did as follows:
string fileList = files.Select(x => x.Remove(0, 2)).ToArray();
var root = new HierarchicalSource("root");
foreach(var f in fileList){
var current = root;
string[] splitFile = f.Split('/');
foreach(var s in splitFile){
if(!current.Children.ContainsKey(s)){
current.Children.Add(s, new List<HierarchicalSource>{ new HierarchicalSource(s) });
}
current = current.Children[s].Last();
}
}
POCO:
public class HierarchicalSource{
public string name;
public Dictionary<string, List<HierarchicalSource>> Children = new Dictionary<string, List<HierarchicalSource>>();
public HierarchicalSource(string name){
this.name = name;
}
}
If I understand you correctly, this requires looping through the array, but it'll allow you to parse each item in the array so you can generate the HierarchicalNode object's values.
var node = new HierarchicalSource();
foreach(var str in files)
{
var pathParts = str.Split('/').ToList();
node.Children.Add(new HierarchicalNode()
{
FullPath = str,
Folder = pathParts[1] // you may need to do some debugging to see what the results for pathParts are instead of just [#]
});
}
Since the FullPath member in HierarchicalNode is public you can set that value without having to go through any constructor.
// using the above code for reference
node.FullPath = whateverThePathYouNeedIs;
Also update that property in the class to use getters and setters
public string FullPath { get; set; }
I have an application where I have a class with 100 property values
For example.
Class RequestData{
String PropertName1 {get;set;}
String PropertName2 {get;set;}
String PropertName3 {get;set;}
.
.
.
String PropertName100 {get;set;}
}
I have a List> and this has all the propertyname and propertyvalues. So, ideally this has
PropertName1 = "Timothy"
PropertName2 = "rajan"
.
.
.
PropertName100 = "alex"
I need to create an instance of RequestData and assign all the property values to each of the property names
In this scenario, I need to do like this which will result in 100s of lines
RequestData requestData = new RequestData ();
requestData.PropertName1 = "Timothy" ;
requestData.PropertName2 = "Rajan" ;
requestData.PropertName3 = "Alex" ;
Is there a better way of doing this? I can loop into the List but not sure how to smartly do it something like
RequestData requestData = new RequestData ();
requestData.[key]= value ;
I hope I made it clear. Any help would be great.
You can do this with reflection
_list = new List<Tuple<string, string>>
{
new Tuple<string, string>("PropertName1", "asd"),
new Tuple<string, string>("PropertName2", "sdfgds"),
new Tuple<string, string>("PropertName3", "dfgdfg"),
new Tuple<string, string>("PropertName100", "dfgdfg")
};
var requestData = new RequestData();
foreach (var tuple in _list)
{
requestData.GetType()
.GetProperty(tuple.Item1, BindingFlags.Public| BindingFlags.NonPublic | BindingFlags.Instance )
?.SetValue(requestData, tuple.Item2);
}
Or an extension method
public void UpdateProperties<T>(this T obj, List<Tuple<string, string>> list) where T : class
{
foreach (var tuple in _list)
{
var type = obj.GetType();
var property = type.GetProperty(tuple.Item1, BindingFlags.Public| BindingFlags.NonPublic | BindingFlags.Instance );
if(property == null)
continue;
property.SetValue(obj, tuple.Item2);
}
}
Full Demo here
Additional Resources
Type.GetProperty Method (String)
Searches for the public property with the specified name.
PropertyInfo.SetValue Method (Object, Object)
Sets the property value of a specified object.
BindingFlags Enumeration
Specifies flags that control binding and the way in which the search
for members and types is conducted by reflection.
Yes, you can do it. Without more specifics though it's very difficult to give a "good" response. Based on what you've shown (and making a probably bad assumption on my part) here is one of several different possible ways to do so. I don't really recommend this personally, but perhaps it (with other answers/comments) will start you down the path that you actually want/need to go.
I should mention that there are more efficient methods for this, but wanted to show a rudimentary method that may be a bit more apparent as to what is actually happening.
static void Main()
{
var propertyList = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("PropertyName1","Value1"),
new KeyValuePair<string, string>("PropertyName2","Value2"),
new KeyValuePair<string, string>("PropertyName3","Value3"),
new KeyValuePair<string, string>("PropertyName4","Value4"),
new KeyValuePair<string, string>("PropertyName5","Value5"),
};
var requestData = new RequestData();
//reflection allows you to loop through the properties of a class
foreach (var property in requestData.GetType().GetProperties())
{
//you can loop through your list (here I made an assumption that it's a list of KeyValuePair)
foreach (var keyValuePair in propertyList)
{
//if the key matches the property name, assign the value
if (property.Name.Equals(keyValuePair.Key))
{
property.SetValue(requestData, keyValuePair.Value);
}
}
}
//to show that they are properly set
Console.WriteLine(requestData.PropertyName1);
Console.WriteLine(requestData.PropertyName2);
Console.WriteLine(requestData.PropertyName3);
Console.WriteLine(requestData.PropertyName4);
}
}
public class RequestData
{
public string PropertyName1 { get; set; }
public string PropertyName2 { get; set; }
public string PropertyName3 { get; set; }
public string PropertyName4 { get; set; }
}
Throwing another similar answer into the ring, this one using a list of strings and splitting them on the = sign, then using reflection to try to get the property name, and if that's not null, set the property value of our object:
private static void Main()
{
var propNamesAndValues = new List<string>
{
"PropertName1 = Timothy",
"PropertName2 = Rajan",
"PropertName100 = Alex",
};
var requestData = new RequestData();
foreach (var propNameValue in propNamesAndValues)
{
var parts = propNameValue.Split('=');
if (parts.Length < 2) continue;
var propName = parts[0].Trim();
var propValue = parts[1].Trim();
typeof(RequestData).GetProperty(propName)?.SetValue(requestData, propValue);
}
Console.WriteLine("{0} {1} {2}", requestData.PropertName1,
requestData.PropertName2, requestData.PropertName100);
GetKeyFromUser("\nDone! Press any key to exit...");
}
Output
I want to use a foreach k, v pairs loop to run through a multidimensional list, and output those values elsewhere. Here is the code:
public class LogTable
{
public string FunctionName { get; set; }
public string LogTime { get; set; }
}
public class TableVars
{
public List<LogTable> loggingTable { get; set; }
public TableVars()
{
loggingTable = new List<LogTable>();
}
public void createLogList()
{
loggingTable = new List<LogTable>();
}
}
foreach( KeyValuePair<string, string> kvp in tablevars.loggingTable)
{
// output would go here. I haven't looked it up yet but I assume it's something
// along the lines of var = k var2 = v? Please correct me if I'm wrong.
}
When I run my mouse over 'foreach' I get a warning saying - 'Cannot convert type 'DataObjects.LogTable' to 'System.Collections.Generic.KeyValuePair. How can I resolve this issue, or is there a more efficient way to accomplish the same goal?
Thanks!
I should have added more context, sorry. I'm trying to return the two different values inside the properties 'FunctionName' and 'LogTime' which I have added via:
var tablevars = new TableVars();
tablevars.loggingTable.Add(new LogTable { FunctionName = errorvalue, LogTime = logtime });
To specify more accurately, the intention of the foreach k, v loop was to grab every distinct property of FunctionName and LogTime and input them into a database in SQL Server. This is why the distinction between k, v (or FunctionName, LogTime) is important. Again, please correct me if I'm wrong.
You cannot use KeyValuePair<>, because you don't enumerate a Dictionary<>. But you don't need to, simply do this:
foreach(LogTable logTable in tablevars.loggingTable)
{
// do whatever with logTable.FunctionName and logTable.LogTime
}
Either change your foreach to iterate through List<LogTable>
foreach( LogTable lt in tablevars.loggingTable)
{...}
OR
Use a KeyValuePair instead of creating class LogTable
public class TableVars
{
public Dictionary<string,string> loggingTable { get; set; }
public TableVars()
{
loggingTable = new Dictionary<string,string>();
}
public void createLogList()
{
loggingTable = new Dictionary<string, string>();
}
}
foreach( KeyValuePair<string, string> kvp in tablevars.loggingTable)
{
//loggingTagle is now a KeyValuePair
}