#region Arthea License
/***********************************************************************
* Arthea MUD by R. Jennings (2007) http://arthea.googlecode.com/ *
* By using this code you comply with the Artistic and GPLv2 Licenses. *
***********************************************************************/
#endregion
using System;
using System.Reflection;
using Arthea.Connections.Players;
using Arthea.Creation.Attributes;
using Arthea.Interfaces;
namespace Arthea.Creation
{
/// <summary>
/// Implementation of a class to edit a field.
/// </summary>
public class OlcField
{
#region [rgn] Fields (3)
private object baseObj;
private FieldInfo info;
private object obj;
#endregion [rgn]
#region [rgn] Constructors (1)
/// <summary>
/// Initializes a new instance of the <see cref="OlcField"/> class.
/// </summary>
/// <param name="obj">The obj.</param>
/// <param name="info">The info.</param>
public OlcField(object obj, FieldInfo info)
{
this.info = info;
baseObj = obj;
this.obj = info.GetValue(obj);
}
#endregion [rgn]
#region [rgn] Properties (4)
/// <summary>
/// Gets or sets the base obj.
/// </summary>
/// <value>The base obj.</value>
public object BaseObj
{
get { return baseObj; }
set { baseObj = value; }
}
/// <summary>
/// Gets or sets the info.
/// </summary>
/// <value>The info.</value>
public FieldInfo Info
{
get { return info; }
set { info = value; }
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return Olc.FieldToWords(info.Name); }
}
/// <summary>
/// Gets or sets the obj.
/// </summary>
/// <value>The obj.</value>
public object Obj
{
get { return obj; }
set { obj = value; }
}
#endregion [rgn]
#region [rgn] Methods (4)
// [rgn] Public Methods (3)
/// <summary>
/// Edits this field.
/// </summary>
/// <param name="player">The player.</param>
/// <param name="argument">The argument.</param>
public void Edit(Player player, String argument)
{
if (CustomEdit(player, argument))
return;
try
{
if (info.FieldType.IsEnum)
{
Set(Enum.Parse(info.FieldType, argument, true));
}
else
{
Set(Convert.ChangeType(argument.ToString(), info.FieldType));
}
player.WriteLine("{0} set to {1}.",
new String(info.Name).Capitalize(), argument);
}
catch (Exception ex)
{
player.WriteLine("Invalid argument: {0}.", ex.Message);
}
}
/// <summary>
/// Gets this instance.
/// </summary>
public object Get()
{
PropertyInfo prop = baseObj.GetType().GetProperty(info.Name,
BindingFlags.IgnoreCase | BindingFlags.Instance |
BindingFlags.Public);
// use a property of field name if it exists
if (prop != null)
{
MethodInfo mi = prop.GetGetMethod();
if (mi != null)
{
return mi.Invoke(baseObj, new object[] {});
}
else
{
Log.Bug("{0} property is write only.", prop.Name);
}
}
return info.GetValue(baseObj);
}
/// <summary>
/// Sets the specified value.
/// </summary>
/// <param name="value">The value.</param>
public void Set(object value)
{
PropertyInfo prop = baseObj.GetType().GetProperty(info.Name,
BindingFlags.IgnoreCase | BindingFlags.Instance |
BindingFlags.Public);
// use a property of field name if it exists
if (prop != null)
{
MethodInfo mi = prop.GetSetMethod();
if (mi != null)
{
mi.Invoke(baseObj, new object[] {value});
return;
}
else
{
Log.Bug("{0} property is read only.", prop.Name);
}
}
info.SetValue(baseObj, value);
}
// [rgn] Private Methods (1)
/// <summary>
/// Checks for a custom edit method in this object being edited.
/// </summary>
/// <param name="player">The player.</param>
/// <param name="argument">The argument.</param>
/// <returns>true if a custom edit method was executed.</returns>
private bool CustomEdit(Player player, String argument)
{
CustomEditType custEd;
if ((obj is CustomEditType) && (custEd = obj as CustomEditType) != null)
{
custEd.CustomEdit(player, this, argument);
return true;
}
object[] atts = info.GetCustomAttributes(typeof (CustomEditAttribute), false);
if (atts.Length == 0)
return false;
else if (atts.Length > 1)
throw new Exception("Ambiguous custom edit attributes.");
CustomEditAttribute custAtt = (atts[0] as CustomEditAttribute);
if (custAtt == null)
throw new Exception("Attribute is not a custom edit attribute.");
MethodInfo mi = baseObj.GetType().GetMethod(custAtt.Method,
BindingFlags.Public | BindingFlags.Instance |
BindingFlags.Static);
if (mi == null)
throw new Exception("Custom edit attribute unable to find method.");
mi.Invoke(baseObj, new object[] {player, this, argument});
return true;
}
#endregion [rgn]
}
}