Sorry im newb and I don't know how to ask my question properly in the title. I have a database:
class PlayerData
{
public ulong id;
public string name;
public int kills;
public int deaths;
}
and I want to return the value corresponding to the requested key
object getStats(ulong uid, string stat)
{
var player = BasePlayer.FindByID(uid);
PlayerData data = PlayerData.Find(player);
object value = data.TryGetValue(stat); // I know this ain't right
return value;
}
example:
int kills = getStats(123456, kills); //will ask for the value of "kills" in the data. Return data.kills
stat could be anything in data (id, name, kills, deaths)
thanks alot!
You could take Sun Maung Oo's suggestion of using a switch statement:
object TryGetValue(int playerId, string name)
{
var player = GetPlayer(playerId);
switch (name)
{
case "name": return name;
case "kills": return kills;
// Other properties
// ...
default: return null;
}
}
Or you could flatten the data:
public class Statistic
{
public int PlayerId { get; set; }
public string Name { get; set; }
public object Value { get; set; }
}
Then finding the value is a matter of finding the statistic with the given player id and name.
I suppose what you are trying to do here is to get the object value base on the object Name? If that is the case, I think you could use reflection to achieve that. You could reference this answer: Get property value from string using reflection in C#
Sample Code:
class PlayerData
{
public ulong id;
public string name;
public int kills;
public int deaths;
}
object getStats(ulong uid, string stat)
{
var player = BasePlayer.FindByID(uid);
PlayerData data = PlayerData.Find(player);
object value = data.GetType().GetProperty(stat).GetValue(data, null);
return value;
}
Related
I would like to know if there is a way to know if a parameter has been set. For example I have my object User.
public class User{
public int Oid{ get; set; }
public string Name{ get; set; }
public string Test{ get; set; }
}
I create an instance of my object and I set the property Oid and Name but not Test. I would like know this.
User u = new User();
u.Oid = 1;
u.Name = "Test";
It's possible?
TY
For reference types, a property (or field) which is not set will have the value null. Because string is a reference type, you can check this very easy:
if(u.Test == null)
{
Console.WriteLine("Property test of variable u is not set!");
}
For other types it is not so easy. bool variables will be false by default, and all numeric values like int uint, double etc will be 0. But of course, somebody might have set it fully aware to these values.
You can get the default value of any type via the following:
int x = default(int); // will be 0
string y = default(y); // will be null
bool z = default(bool); // will be false;
ADDENDUM: A completely different approach will be the following:
public class User{
public int Oid{ get; set; }
public string Name{ get; set; }
private string test;
public string Test
{
get { return test; }
set {test = value; IsTestSet = true; }
}
public bool IsTestSet {get; private set;}
}
With this code, you can check the property IsTestSet to determine whether the setter was called at least once.
This's my personal solution.
public short oid;
public short Oid
{
get { return oid; }
set
{
oid = value;
AddListaSet("Oid");
}
}
// for all parameter
List<string> ListSet { get; set; } = new List<string>();
private void AddListSet(string name)
{
if (ListSet.Contains(name) == false)
ListSet.Add(name);
}
public bool IsSet(string name)
{
return ListSet.Contains(name) ? true : false;
}
I have this class that contains a static list
public class TypeList
{
public string Name;
public string NameTag;
public TypeList(string Name, string NameTag)
{
this.Name = Name;
this.NameTag = NameTag;
}
public static List<TypeList> DataType = new List<TypeList>() {
new TypeList("DataType","-1"),
new TypeList("OpOne","1"),
new TypeList("OpTwo","2"),
};
}
I then put the static list called DataType into a combobox:
public void RefreshList()
{
List<TypeList> data = new List<TypeList>();
data = TypeList.DataType;
typeCB.DataSource = data;
typeCB.DisplayMember = "Name";
typeCB.ValueMember = "NameTag";
typeCB.SelectedValue = -1;
typeCB.SelectedText = "Select DataType";
}
However, when I run it, all I get are the classnames in my combobox. Is something wrong with my code? I tried to do
data.Select(x=>x.Name).ToList()
But that just gives me the name portion.
I might be wrong, but based on the Documentation and Example it might be that this Feature only works with public property getters, not public fields:
Gets or sets the property to display for this ListControl.
public class USState
{
private string myShortName;
private string myLongName;
public USState(string strLongName, string strShortName)
{
this.myShortName = strShortName;
this.myLongName = strLongName;
}
public string ShortName
{
get
{
return myShortName;
}
}
public string LongName
{
get
{
return myLongName;
}
}
}
Of course I would also advise against making the list a part of the Type class. A simple Programm scope static would be better. If that is the case and as autoproties have have become a thing by now, this should be enough of a fix:
public class Type
{
public string Name { private set; get } ;
public string NameTag {private set; get };
public TypeList(string Name, string NameTag)
{
this.Name = Name;
this.NameTag = NameTag;
}
}
//use in the class of main, the form or some similar central point
static List<Type> TypeList = new List<Type>();
I am trying to use JavaScriptSerializer and I have got good results when I want to serialize a list of objects of a class like
public class employee
{
public string id; //unique id of the employee
public string displayName;
public int displayFlag;
public employee(string i, string dN, int dF)
{
id = i;
displayName = dN;
displayFlag = dF;
}
}
public class data2
{
public List<employee> detail;
}
When I do the following
var json = new JavaScriptSerializer();
string jsonData = json.Serialize(data2);
(and data2 is an object of class data2)
However when I try to do the same for something a little more complicated such as
public class Ccanister
{
string identifier;
public Ccanister(string c)
{
identifier = c;
}
}
public class medicine
{
public string id; //unique id
public string displayName;
//and here an array of canisters
public List<Ccanister> canister;
}
public class dataMedicine
{
public List<medicine> detail; //Change this
}
and I do this
string jsonMedi = json.Serialize(dataM);
I got wrong results.
dataM has correct results (I debugged it) but when jsonMedi gets its results, the canister list 'canister' is always empty. (It was not empty in dataM)
I wonder what I am doing wrong here
I have something like:
class ABC
{
public int id { get; set; }
public string name { get; set; }
public int value { get; set; }
}
And json like {"name":"John","value":123}
I want to parse this json and create an ABC for a specified id value. I wondered if I have to do this in two steps or can pass the id in somehow? Ideally these fields would be readonly but I'm not sure if JSON.net allows that.
e.g. a method like ABC getABC(int id, string json)
It's a bit code-golfy, but you want to make the members of ABC readonly, then deserialize JSON into an instance of ABC while passing in a specified id using just one line of code, you can do:
var abc = new JObject(new[] { new JProperty("id", id) }.Concat(JObject.Parse(json).Properties())).ToObject<ABC>();
Using the class:
class ABC
{
readonly int m_id;
readonly string m_name;
readonly int m_value;
public ABC(int id, string name, int value)
{
this.m_id = id;
this.m_name = name;
this.m_value = value;
}
public int id { get { return m_id; } }
public string name { get { return m_name; } }
public int value { get { return m_value; } }
}
This takes advantage of the fact that, if an object has a single public parameterized constructor, Json.NET will invoke it to construct the object, matching argument names to JSON property names. Thus you can pass the id in by parsing the JSON to a JObject, merging in the id, then deserializing to your final class.
A less code-golfy solution would be to do:
var abc = JObject.Parse(json).WithProperty("id", id).ToObject<ABC>();
Using the fluent extension method:
public static class JsonExtensions
{
public static JObject WithProperty(this JObject obj, string name, JToken value)
{
obj = obj ?? new JObject();
obj[name] = value;
return obj;
}
}
I have a similar problem like this :
Many to many object to object relation in C#
However, imagine that the Championship would have a "Last Date Played" property (just as an example) that would map to any Participant. In this case, where would that property end up? Is it a must to create an intermediate class? (which i wouldn't want to do) what option do i have? thanks!
One way would be to have an array on each object containing pointers to the other objects either via an dictionary that stores the object as key and date as value (or a custom property class for any number of properties) or using a wrapper class around the object and a plain list, this wrapper should then implement the decorator pattern to allow direct access to the object together with any unique properties.
The wrapper object could use an internal object for the properties that is shared between the oposing wrapper objects for the 2 different objects so that any property is in sync.
Another way would be a separate list of pairs where one is wrapped like the above.
The later makes it easy to loop over all objects.
Here is a code example, it might not be exactly what you need but it might give you the basics of my idea.
void Main()
{
var p = new Player("David");
var c = new Championship("Chess");
p.LinkChampionship(c, DateTime.Now);
p.Dump();
}
// Define other methods and classes here
class Player : Properties {
public virtual String Name {get; set;}
public List<ChampionshipWrapper> champs = new List<ChampionshipWrapper>();
public Player() {
}
public Player(string name) {
Name = name;
}
public void LinkChampionship(Championship champ, DateTime when) {
var p = new Properties(when);
champs.Add(new ChampionshipWrapper(champ, p));
champ.players.Add(new PlayerWrapper(this, p));
}
}
class Championship : Properties {
public virtual String Name { get; set; }
public List<PlayerWrapper> players = new List<PlayerWrapper>();
public Championship(){}
public Championship(string name) {
Name = name;
}
public void LinkPlayer(Player play, DateTime when) {
var p = new Properties(when);
players.Add(new PlayerWrapper(play, p));
play.champs.Add(new ChampionshipWrapper(this, p));
}
}
class Properties {
public virtual DateTime LastPlayed { get; set; }
public Properties() {
}
public Properties(DateTime when) {
LastPlayed = when;
}
}
class PlayerWrapper : Player {
private Player player;
private Properties props;
public PlayerWrapper(Player play, Properties prop) {
this.player = play;
this.props = prop;
}
public override String Name {
get { return this.player.Name; }
set { this.player.Name = value; }
}
public override DateTime LastPlayed {
get { return this.props.LastPlayed; }
set { this.props.LastPlayed = value; }
}
}
class ChampionshipWrapper : Championship {
private Championship champ;
private Properties props;
public ChampionshipWrapper(Championship c, Properties prop) {
this.champ = c;
this.props = prop;
}
public override String Name {
get { return this.champ.Name; }
set { this.champ.Name = value; }
}
public override DateTime LastPlayed {
get { return this.props.LastPlayed; }
set { this.props.LastPlayed = value; }
}
}