Jump to content

Component & Property/Attribute design C# Thread


Davaris
 Share

Recommended Posts

I thought I'd post this here, because we are writing C# code and I don't want to keep bugging the C++ people with what we are doing.

 

This is the original thread, if you want to see what we were talking about:

http://leadwerks.com/werkspace/index.php?/topic/2150-component-propertyattribute-design/

 

What I am working on is similar to Rick's component idea but is also very different, in that you no longer have objects containing private data and the functions that operate on them.

 

You have data as a separate entity and functions as separate entities. When the functions want to do something, they access the data pool.

 

The other big idea, is you can stack data on top of each other, in a hierarchy to build up complexity and if you write a wrapper class (AKA Decorator) as described below, you can share a common pool of data with all your game entities.

 

I took the idea from this excellent article. Read it to get an idea of what my code does:

http://steve-yegge.blogspot.com/2008/10/universal-design-pattern.html

 

You can write a wrapper class for it that provides a second parent pointer, so you can share all the parent data among your game entities base data. All it has to do is change StateCore's parent pointer to its own, before it performs an operation and then restore it when it is complete.

 

As for permission, you are free to use this code in commercial or free projects, as long as you take full responsibility if it causes any damage. Also if you see a way to improve it, let me know as I am a C# newbie.

 

TBH, it is probably safer to get the general idea and write your own. :)

 

namespace Game
{
   public class StateCore
   {
       // OrderedDictionary sorts as it inserts (bah!)
       // LinkedHashMap maintains insertion order, but you have to buy a decent one
       // and I don't know if it works on anything other than PC
       private OrderedDictionary<string, object> mList;

       private string mName;
       private StateCore mParent;
       public const string cBlank = "$_Blank_$";
       private bool mIsReadOnly;

       public string Name { get { return mName; } set { mName = value; } }
       public OrderedDictionary<string, object> List { get { return mList; } }
       public StateCore Parent { get { return mParent; } set { mParent = value; } }
       public bool IsReadOnly { get { return mIsReadOnly; } set { mIsReadOnly = value; } }

       public StateCore(string name)
       {
           mName = name;
           mList = new OrderedDictionary<string, object>();
           mParent = null;
           mIsReadOnly = false;
       }

       public bool Put<T>(string key, T val)
       {
           AssertIsReadOnly();
           AssertTypeCompatibiltyAll<T>(key);

           if (PutPrivate<T>(key, val))
           {
               DebugPrintKeyVal("Put", key);
               return true;
           }
           return false;
       }
       public bool Get<T>(string key, ref T ret_val)
       {
           object val;

           for (StateCore p = this; p != null; p = p.mParent)
           {
               if (p.mList.TryGetValue(key, out val))
               {
                   if (p.IsBlank(val)) return false;// not present
                   p.AssertTypeCompatibiltyVal<T>(val);
                   p.DebugPrintKeyVal("Get", key);
                   ret_val = (T)val;
                   return true;
               }
           }
           return false; // not present
       }
       public bool Has<T>(string key)
       {
           object val;

           for (StateCore p = this; p != null; p = p.mParent)
           {
               if (p.mList.TryGetValue(key, out val))
               {
                   if (p.IsBlank(val)) return false;// not present
                   p.AssertTypeCompatibiltyVal<T>(val);
                   p.DebugPrintKeyVal("Has", key);
                   return true;
               }
           }
           return false;// not present
       }
       public bool Remove<T>(string key)
       {
           object val;

           AssertIsReadOnly();

           if (mList.TryGetValue(key, out val))
           {
               if (!IsBlank(val))
                   AssertTypeCompatibiltyAll<T>(key);

               DebugPrintKeyVal("Remove", key);
               mList.Remove(key);
               return true;
           }
           return true;
       }
       public bool SetIsBlank<T>(string key)
       {
           AssertIsReadOnly();
           AssertTypeCompatibiltyAll<T>(key);
           if (PutPrivate(key, cBlank))
           {
               DebugPrintKeyVal("SetIsBlank", key);
               return true;
           }
           return false;
       }

       public void PrintContents()
       {

           Console.WriteLine("****************************");
           Console.WriteLine("PrintContents");
           Console.WriteLine("****************************");

           for (StateCore p = this; p != null; p = p.Parent)
           {
               Console.WriteLine("");
               Console.WriteLine("CONT = {0}", p.Name);
               Console.WriteLine("");

               foreach (KeyValuePair<string, object> entry in p.List)
               {
                   if (entry.Value == null)
                       Console.WriteLine("({0}, null) TYPE: null", entry.Key);
                   else
                       Console.WriteLine("({0}, {1}) TYPE: {2}", entry.Key, entry.Value, entry.Value.GetType());
                   Console.WriteLine("");
               }
           }
           Console.WriteLine("");
       }

       // *****************

       private bool PutPrivate<T>(string key, T val)
       {
           object ret_val;

           // Cannot put null values
           if (val == null)
               throw new Exception("null values are not allowed");

           // assert key type is allowed
           GameState.AssertObjectType(val.GetType());

           if (mList.TryGetValue(key, out ret_val))
           {
               if (!((T)val).Equals(ret_val)) // val will be changed
               {
                   mList[key] = val;
                   return true;
               }
           }
           else // new key
           {
               mList.Add(key, val);
               return true;
           }
           return false; // no change
       }

       private bool IsBlank(object val)
       {
           return val.GetType() == cBlank.GetType() && ((string)val) == cBlank;
       }
       private void AssertTypeCompatibiltyVal<T>(object val)
       {
           if (val.GetType() != typeof(T))
               throw new Exception("Type is incompatible");
       }
       private void AssertTypeCompatibiltyAll<T>(string key)
       {
           object val;

           for (StateCore p = this; p != null; p = p.mParent)
           {
               if (p.mList.TryGetValue(key, out val))
               {
                   p.AssertTypeCompatibiltyVal<T>(val);
                   break;
               }
           }
       }
       private void DebugPrintKeyVal(string function, string key)
       {
           /*
           if (mList[key] == null)
               Console.WriteLine("{0}: ({1},null) TYPE: null, CONT: {2}", function, key, Name);
           else
               Console.WriteLine("{0}: ({1},{2}) TYPE: {3}, CONT: {4}", function, key, mList[key], mList[key].GetType(), Name);

           Console.WriteLine("");
           */
       }
       private void AssertIsReadOnly()
       {
           if (mIsReadOnly)
               throw new Exception(string.Format("{0} is read only and cannot be altered", Name));
       }
   }
}

Win 7 Pro 64 bit

AMD Phenom II X3 720 2.8GHz

GeForce 9800 GTX/9800 GTX+

4 GB RAM

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...