Creating dynamic variable names in C#

孤街醉人 提交于 2019-12-18 04:23:12

问题


I am trying to write a simple role playing game in C# to become more familiar with the language.

I have a class that loads data from CSV file, creates an object, and places it in a dictionary. Because every aspect of the game has different data (items, actors, skills, etc), I have set up each of these as a class, but this requires me to re-implement a Load() method for each one. After doing this 5 or 6 times, I am wondering if there isn't a better way to implement this.

Basically, what I would want to do is parse over the first line of the CSV which contains headers, and use these as class variable names. Currently, they are implemented as a dictionary relationship, so I would do SomeClassInstance.dict["id"], where I would ideally type SomeClassInstance.id, which is entirely generated from the contents of the file.

Is that a thing? How do I do this?


回答1:


If you stick to your current design (CSV + dictionary) you could use the ExpandoObject class to get what you are looking for, create a simple factory class:

public static class ObjectFactory
{
    public static dynamic CreateInstance(Dictionary<string, string> objectFromFile)
    {
        dynamic instance = new ExpandoObject();

        var instanceDict = (IDictionary<string, object>)instance;

        foreach (var pair in objectFromFile)
        {
            instanceDict.Add(pair.Key, pair.Value);
        }

        return instance;
    }
}

This factory will create an object instance of whatever dictionary you give it, i.e. just one method to create all your different kinds of objects. Use it like this:

   // Simulating load of dictionary from file
   var actorFromFile = new Dictionary<string, string>();

   actorFromFile.Add("Id", "1");
   actorFromFile.Add("Age", "37");
   actorFromFile.Add("Name", "Angelina Jolie");

   // Instantiate dynamically
   dynamic actor = ObjectFactory.CreateInstance(actorFromFile);

   // Test using properties
   Console.WriteLine("Actor.Id = " + actor.Id + 
                     " Name = " + actor.Name + 
                     " Age = " + actor.Age);
   Console.ReadLine();

Hopes this helps. (And yes she was born 1975)




回答2:


You need to read up on serialization - instead of holding the files in CSV files, you can store them in a serialized format and load them directly into the wanted type.

You will only need a couple of methods to serialize and deserialize.

I suggest reading up on:

  • XmlSerializer
  • BinaryFormatter
  • DataContractSerializer
  • JavaScriptSerializer
  • protobuf.net
  • json.net

The above links are to different serializers (and I have certainly left some off - anyone in the know, if there is a good serializer that you know, please add) - read through, see their APIs, play around with them and see their on-disk formats and make your decision.




回答3:


Derive from DynamicObject and override TryGetMember so that it returns the appropriate dictionary entry. Exactly what Microsoft did in MVC 3's ViewBag. Example usage (if your derived type was named CsvBag):

dynamic bag = new CsvBag(csvFileStream);
_monitor.Monster.LookUp(*bag.Id*).Attack(player); // whatever.. 



回答4:


Why not create a manager object responsible for reading data and returning instances of specified objects? Something like:

var actors = ActorsLoader.Load("actors.cvs");

where ActorsLoader.Load could be implemented as:

IEnumerable<Actor> Load( string fileName )
{
    //1. reading each line (each line = new actor) & creating actor object
    //2. adding created actor object to a collection
    //3. returning back a collection
}

I have assumed that each type of in-game objects are stored in separate files (so that you have: actors.csv, items.csv, skills.csv etc.)



来源:https://stackoverflow.com/questions/11891381/creating-dynamic-variable-names-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!