I currently have a helper class that I am using to obfuscate a static class that keeps track of high scores in a game I am working on. I am using Eazfuscator on my release and found that when my scores were being serialized, this exception was thrown:
ArgumentException Identifier ' ' is not CLS-compliant
Is there a way I can store my list of high scores in my helper class and still be able to serialize it after obfuscation?
try
{
GameHighScore highScoreHelper = new GameHighScore();
highScoreHelper.CreateGameHighScore(highScore);
XmlSerializer serializer = new XmlSerializer(typeof(GameHighScore));
serializer.Serialize(stream, highScoreHelper);
}
catch(Exception e)
{
Logger.LogError("Score.Save", e);
}
My helper class:
public class GameHighScore
{
public List<HighScoreStruct<string, int>> highScoreList;
private HighScoreStruct<string, int> scoreListHelper;
[XmlType(TypeName = "HighScore")]
public struct HighScoreStruct<K, V>
{
public K Initials
{ get; set; }
public V Score
{ get; set; }
public HighScoreStruct(K initials, V score) : this()
{
Initials = initials;
Score = score;
}
}
public GameHighScore()
{
highScoreList = new List<HighScoreStruct<string, int>>();
scoreListHelper = new HighScoreStruct<string, int>();
}
public void CreateGameHighScore(List<KeyValuePair<string, int>> scoreList)
{
for (int i = 0; i < scoreList.Count; i++)
{
scoreListHelper = new HighScoreStruct<string, int>(scoreList[i].Key, scoreList[i].Value);
highScoreList.Add(scoreListHelper);
}
}
}
Best solution would be not to obfuscate classes needed for any kind of serialization. You'll gain 2 benefits of doing so:
no strange names will be used for classes
re-running obfuscation will not produce new names for the same classes/fields.
Most obfuscators allow to specify attributes that keep particular classes/methods non-obfuscated.
Otherwise - write your own serialization.
Try using the XmlElement attribute on your properties.
Related
I'm trying to implement a class with a property which can be accessed only with parameter. To clear my question see how I intend to use it
Note that this is different than Indexer. Please don't flag for duplicate.
My incomplete class
public class Inventory{
public object Options..... // I don't know how to define this property
}
How I'm going to use it
Inventory inv = new Inventory();
string invLabel = (string)inv.Options["Label"];
int size = inv.Options["Size"];
inv.Options["Weight"] = 24;
Internally, Options reads data from a private Dictionary. Please help me on how I can define the Options property.
Note: This is different than Indexer. With Indexer, I can use below code:
int size = inv["Size"];
But my usage is different.
I found a way to implement it.
public class Options
{
public Dictionary<string, object> _options;
public Options()
{
_options = new Dictionary<string, object>();
}
public object this[string key] {
get { return _options.Single(r => r.Key == key).Value; }
set { _options[key] = value; }
}
}
public class Inventory
{
public Inventory()
{
Options = new Options();
}
public Options Options { get; set; }
}
Usage:
var x = new Inventory();
x.Options["Size"] = 120;
x.Options["Box"] = "4 x 4 x 8";
Console.WriteLine(x.Options["Size"]);
Console.WriteLine(x.Options["Box"]);
class Program
{
static void Main(string[] args)
{
JSONClass jsonClass = new JSONClass();
JSONElement el = new JSONElement
{
A = 5,
B = "test1"
};
JSONElement el2 = new JSONElement
{
A = 3,
B = "test2"
};
jsonClass.JSONList.Add(el);
jsonClass.JSONList.Add(el2);
var output = JsonSerializer.Serialize<JSONClass>(jsonClass);
Console.WriteLine(output);
}
}
public class JSONClass
{
public List<JSONElement> JSONList = new List<JSONElement>();
}
public class JSONElement
{
public int A { get; set; }
public string B { get; set; }
}
This code returns {} which means that JsonSerializer.Serialize failed to do what it supposed to do. I imagine its because its not smart enough to handle custom types. And here is my question, how to do it. Internet is full of articles how to write custom converters etc, but none of them mention custom types.
Your JSONList member is a public field - whereas JsonSerializer looks for properties.
Change your code for JSONClass to this:
public class JSONClass
{
public List<JSONElement> JSONList { get; } = new List<JSONElement>();
}
The output is then:
{"JSONList":[{"A":5,"B":"test1"},{"A":3,"B":"test2"}]}
The bigger lesson to learn here is not to assume that the mistake is in the library you're using. Always start with an expectation that the problem is in your own code. Sometimes you'll find it really is in the library or system code (or in the compiler etc) but in my experience that's relatively rare.
I have a question since I'm new in programming Im really confused about how to implement a best practice solution for the following problem, Its a game logic,here are the possible ways of making points
EnemyA 400,
EnemyB 500,
EnemyC 700,
Coin 200,
FireBall 300
means hitting Coin gives you 200 points and shooting FireBall gives you 300 &...
if you reach 1000 points you will get an extra life, the logic simple but implementing the best practice is not(at least to me)should I use abstract class or Dictionary?
So far, I used a Dictionary, I read a given file (txt) file which is written (EnemyA,EnemyB,Coin,Coin,Coin,Coin) then I calculate the points:
public int pointCal(IEnumerable<string> enemyType)
{
var possiblePoints = new Dictionary< EnemisEntity,int>()
{
{new EnemisEntity{enemyType="EnemyA"},400 },
{new EnemisEntity{enemyType="EnemyB" },500 },
{new EnemisEntity{enemyType="EnemyC"},700 },
{new EnemisEntity{enemyType="Fireball"},300 },
{new EnemisEntity{enemyType="Coin"},200 },
};
int z=0;
List<int> myPoints=new List<int> ();
foreach (var item in enemyType)
{
z = possiblePoints.FirstOrDefault(f => f.Key.enemyType.Equals(item)).Value;
myPoints.Add(z);
}
int finalPonts= g.Sum(s=>Convert.ToInt32(s));
return finalPonts;
}
Enemy entity class:
public class EnemisEntity
{
public string enemyType { get; set; }
}
It depends. Are the enemies different types of objects (with different properties and such)?
Then it might make sense to create an abstract class and child classes.
public abstract class Shootable {
public int points;
}
public class EnemyA: Shootable {
}
public class EnemyB: Shootable {
}
public class Coin: Shootable {
}
// etc
If all your items are just shootable with one description, then
public class Shootable {
public int points { get; set; }
public string enemyType { get; set; }
public Shootable(int points, string enemyType ){
this.points = points;
this.enemyType = enemyType;
}
}
// then create like
var coin = new Shootable(500, "coin");
If all enemies can be modeled in the same class, then you only need shootable class
Then get the points:
IEnumerble<Shootable> shootableItems = GetShootableFromFile();
var score = shootableItems.Sum(s => s.Points);
You GetShootableFromFile should create one object per file row. So it is a viable situation to create the same objects twice:
// This is a mock to indicate multiple instances of the same class.
public IEnumerble<Shootable> GetShootableFromFile() {
List<Shootable> shootable = new List<Shootable>();
shootable.Add(new Shootable(500,"coin"));
shootable.Add(new Shootable(500,"coin"));
shootable.Add(new Shootable(500,"coin"));
shootable.Add(new Shootable(300,"enemyA"));
shootable.Add(new Shootable(300,"enemyB"));
// etc
}
To me, this is a question of design. When the only difference between enemies is just the value of points as well as their name it is not a good idea to define a class hierarchy. The only thing different between a EnemyA and a EnemyB class would be just the values contained within each class. So you can use a single common class to hold information for each enemy and process the points.
Below is the simplest working prototype that I could code that implements this design. It relies on two classes. The EnemyEntity class to hold the type of enemy and its points, and a Game class that contains the logic behind scoring and keeping a record of all possible enemies.
public class EnemyEntity
{
public EnemyEntity(string type, int points)
{
Type=type;
Points=points;
}
public string Type { get; }
public int Points { get; }
}
public class Game
{
public Game(params (string type, int points)[] values)
{
this.Enemies = new List<EnemyEntity>();
foreach (var (type, points) in values)
{
Enemies.Add(new EnemyEntity(type, points));
}
}
public List<EnemyEntity> Enemies { get; }
public int CalculatePoints(IEnumerable<string> targets)
{
int points = 0;
foreach (var item in targets)
{
var target = Enemies.FirstOrDefault((enemy) => enemy.Type.Equals(item));
if (target!=null)
{
points+= target.Points;
}
}
return points;
}
}
class Program
{
static void Main(string[] args)
{
var game = new Game(
("EnemyA", 400),
("EnemyB", 500),
("EnemyC", 700),
("Coin", 200),
("FireBall", 300));
var input = "EnemyA,EnemyB,Coin,Coin,Coin,Coin";
var targets = input.Split(',');
var points = game.CalculatePoints(targets);
Console.WriteLine(points);
// 1700
}
}
NOTES:
The simplest approach is to use a List<EnemyEntity> and do the lookup with .FirstOrDefault(). I could use a Dictionary<string,EnemyEntity> which would simplify the lookup process. Here is how the Game class would change using a dictionary.
public class Game
{
public Game(params (string type, int points)[] values)
{
this.Enemies = new Dictionary<string, EnemyEntity>();
foreach (var (type, points) in values)
{
Enemies[type] = new EnemyEntity(type, points);
}
}
public Dictionary<string, EnemyEntity> Enemies { get; }
public int CalculatePoints(IEnumerable<string> targets)
{
int points = 0;
foreach (var item in targets)
{
var target = Enemies[item];
if (target!=null)
{
points+= target.Points;
}
}
return points;
}
}
How to pass by ref different types of objects that have the same properties inside and populate them without interface.
In my app there are totally different types which have some properties in common.
Let's say this properties are double arrays.
double[] samples;
Now I have to populate these samples for 20 objects.
I don't have any access to the class definition of this object, so I can't make interface, or make them inherit from a base class.
How can use one method which I call and this method to populate all my properties.
I want to have one method like this:
private static void FillSamples(ref WhoKnowsWhat dataType, MyObject theSamples)
{
for (int i = 0; i < sampleCount; i++)
{
dataType.SampleLength[i] = MyObject.X[i];
dataType.SampleValue[i] = MyObject.y[i];
}
}
And call this with totally different types.
FillSamples(ref BigStruct.OneTypeMine, theSamples);
FillSamples(ref BigStruct.AnotherTypeMine, theSamples);
FillSamples(ref BigStruct.HisType12345, theSamples);
Then the big struct should have these samples filled in the end.
Is there a way in C#?
Thanks!
You can use the dynamic keyword:
private static void FillSamples(dynamic dataType, MyObject theSamples)
{
for (int i = 0; i < sampleCount; i++)
{
dataType.SampleLength[i] = MyObject.X[i];
dataType.SampleValue[i] = MyObject.y[i];
}
}
Edit:
Using reflection (if you don't use .Net 4.0 or higher):
private static void FillSamples(object dataType, MyObject theSamples)
{
Type t = dataType.GetType();
var px = t.GetProperty("SampleLength");
var py = t.GetProperty("SampleValue");
for (int i = 0; i < sampleCount; i++)
{
px.SetValue(dataType, MyObject.X[i], null);
py.SetValue(dataType, MyObject.Y[i], null);
}
}
Don't know if it helps you any, but you can use reflection to find out what properties (and fields, methods etc.) an object supports at runtime. Check out http://www.csharp-examples.net/reflection-property-names/ for example, if you're interested in learning more.
You can use dynamic objects. You should be careful when targeting fields of a dynamic object since they cannot be checked at compile time. See my example below:
[TestFixture]
public class DynamicObjects
{
[Test]
public void Dynamic_Call()
{
dynamic obj1 = new Apple();
obj1.Weight = 100;
obj1.Color = "Red";
dynamic obj2 = new Orange();
obj2.Weight = 200;
obj2.Width = 10;
Assert.IsTrue(obj1.Weight < obj2.Weight);
}
}
public class Apple
{
public int Weight { get; set; }
public string Color { get; set; }
}
public class Orange
{
public int Weight { get; set; }
public int Width { get; set; }
}
I'm having some issues reading the properties of an item I have placed into an arraylist and I can't find the answer anywhere.
ArrayList itemsArrayList = new ArrayList();
itemsArrayList.Add(abyssalScepter);
itemsArrayList.Add(aegisOfTheLegion);
itemInBuildAbilityPower = itemsArrayList[0].abilityPower;
I need to be able to read the properties of the objects in the array so I can apply their values elsewhere but this gets me nowhere.
You need to cast object to the expected type (and hope it's really of this type).
itemInBuildAbilityPower = ((Item)itemsArrayList[0]).abilityPower;
The better option (if the infrastructure code is yours) to use generic container, e.g. List<T>.
List<Item> itemsArrayList = new List<Item>
itemsArrayList.Add(abyssalScepter);
itemsArrayList.Add(aegisOfTheLegion);
itemInBuildAbilityPower = itemsArrayList[0].abilityPower;
try
var itemInBuildAbilityPower = itemsArrayList[0].GetType().GetProperty ("abilityPower").GetGetMethod().Invoke (itemsArrayList[0], null);
Building on elder_george's answer, here is an example of what you could do if abyssalScepter and aegisOfTheLegion are not the exact same type:
using System.Collections.Generic;
class Power { }
interface IAbilityPower { Power abilityPower { get; set; } }
class Scepter : IAbilityPower { public Power abilityPower { get; set; } }
class Aegis : IAbilityPower { public Power abilityPower { get; set; } }
class Test
{
public static void Main()
{
var abyssalScepter = new Scepter();
var aegisOfTheLegion = new Aegis();
var itemsList = new List<IAbilityPower>();
itemsList.Add(abyssalScepter);
itemsList.Add(aegisOfTheLegion);
var power = itemsList[0].abilityPower;
}
}