using System; using System.Collections.Generic; using System.Text; namespace ScriptNET.Runtime { /// /// Represents implementation of Expando object via IScriptable interface. /// By default Expando objects created with a following syntax construct: /// [name->valueExpression, name->valueExpression]; /// This default type may be overriden by ScriptableObjectType option /// in script configuration. /// public class Expando : IScriptable, ISupportAssign { #region Fields Dictionary fields = new Dictionary(); #endregion #region Public Members public IEnumerable Fields { get { return fields.Keys; } } public void AssignTo(object target) { foreach (string field in Fields) { IMemberBind bind = RuntimeHost.Binder.BindToMember(target, field, false); if (bind != null) bind.SetValue(fields[field]); //RuntimeHost.Binder.Set(field, target, fields[field], false); } } public object this[string fieldName] { get { if (fields.ContainsKey(fieldName)) return fields[fieldName]; return null; } } public override string ToString() { bool first = true; StringBuilder builder = new StringBuilder("["); foreach (string field in Fields) { if (!first) builder.Append(','); else first = false; builder.Append(field); builder.Append("->"); object value = this[field]; if (value == null) builder.Append("null"); else builder.Append(value.ToString()); } builder.Append("]"); return builder.ToString(); } #endregion #region IScriptable [Bindable(false)] public virtual object Instance { get { return this; } } [Bindable(false)] public virtual IMemberBind GetMember(string name, params object[] arguments) { if (arguments != null && arguments.Length != 0) return null; return new ExpandoBind(this, name); } [Bindable(false)] public virtual IObjectBind GetMethod(string name, params object[] arguments) { if (arguments != null && arguments.Length != 0) return null; if (!fields.ContainsKey(name)) throw new ScriptMethodNotFoundException(name); return new ExpandoBind(this, name); } #endregion #region ExpandoBind protected class ExpandoBind : IMemberBind { Expando expando; string name; public ExpandoBind(Expando expando, string name) { this.expando = expando; this.name = name; } #region IMemberBind public object Target { get { return expando; } } public Type TargetType { get { return typeof(object); } } public System.Reflection.MemberInfo Member { get { throw new NotSupportedException(); } } public void SetValue(object value) { if (expando.fields.ContainsKey(name)) { expando.fields[name] = value; } else { expando.fields.Add(name, value); } } public object GetValue() { if (!expando.fields.ContainsKey(name)) throw new ScriptIdNotFoundException(name); return expando.fields[name]; } public void AddHandler(object value) { throw new NotSupportedException(); } public void RemoveHandler(object value) { throw new NotSupportedException(); } #endregion #region IInvokable public bool CanInvoke() { return true; } public object Invoke(IScriptContext context, object[] args) { IInvokable method = GetValue() as IInvokable; if (method != null) return method.Invoke(context, args); throw new ScriptIdNotFoundException(string.Format("Method {0} not found", name)); } #endregion } #endregion } }