| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading;
- using MoonSharp.Interpreter.Execution;
- namespace MoonSharp.Interpreter.Interop
- {
- public class StandardUserDataDescriptor : IUserDataDescriptor
- {
- public string Name { get; private set; }
- public Type Type { get; private set; }
- public InteropAccessMode AccessMode { get; private set; }
- public string FriendlyName { get; private set; }
- private Dictionary<string, StandardUserDataMethodDescriptor> m_Methods = new Dictionary<string, StandardUserDataMethodDescriptor>();
- private Dictionary<string, StandardUserDataPropertyDescriptor> m_Properties = new Dictionary<string, StandardUserDataPropertyDescriptor>();
- protected internal StandardUserDataDescriptor(Type type, InteropAccessMode accessMode, string friendlyName)
- {
- if (accessMode == InteropAccessMode.Default)
- accessMode = UserData.DefaultAccessMode;
- Type = type;
- Name = type.FullName;
- AccessMode = accessMode;
- FriendlyName = friendlyName;
- if (AccessMode != InteropAccessMode.HideMembers)
- {
- foreach (ConstructorInfo ci in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
- {
- if (CheckVisibility(ci.GetCustomAttributes(true), ci.IsPublic))
- {
- var md = new StandardUserDataMethodDescriptor(ci, this.AccessMode);
- m_Methods.Add("__new", md);
- break;
- }
- }
- foreach (MethodInfo mi in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Static))
- {
- if (CheckVisibility(mi.GetCustomAttributes(true), mi.IsPublic))
- {
- if (mi.IsSpecialName)
- continue;
- var md = new StandardUserDataMethodDescriptor(mi, this.AccessMode);
- if (m_Methods.ContainsKey(md.Name))
- continue;
- //throw new ArgumentException(string.Format("{0}.{1} has overloads", Name, md.Name));
- m_Methods.Add(md.Name, md);
- }
- }
- foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
- {
- if (CheckVisibility(pi.GetCustomAttributes(true), IsPropertyInfoPublic(pi)))
- {
- var pd = new StandardUserDataPropertyDescriptor(pi, this.AccessMode);
- m_Properties.Add(pd.Name, pd);
- }
- }
- }
- }
- private bool IsPropertyInfoPublic(PropertyInfo pi)
- {
- MethodInfo getter = pi.GetGetMethod();
- MethodInfo setter = pi.GetSetMethod();
- return (getter != null && getter.IsPublic) || (setter != null && setter.IsPublic);
- }
- private bool CheckVisibility(object[] attributes, bool isPublic)
- {
- MoonSharpVisibleAttribute va = attributes.OfType<MoonSharpVisibleAttribute>().SingleOrDefault();
- if (va != null)
- return va.Visible;
- else
- return isPublic;
- }
- public DynValue Index(Script script, object obj, DynValue index)
- {
- if (index.Type != DataType.String)
- throw ScriptRuntimeException.BadArgument(1, string.Format("userdata<{0}>.__index", this.Name), "string", index.Type.ToLuaTypeString(), false);
- DynValue v = TryIndex(script, obj, index.String);
- if (v == null) v = TryIndex(script, obj, UpperFirstLetter(index.String));
- if (v == null) v = TryIndex(script, obj, Camelify(index.String));
- if (v == null) v = TryIndex(script, obj, UpperFirstLetter(Camelify(index.String)));
- return v;
- }
- protected virtual DynValue TryIndex(Script script, object obj, string indexName)
- {
- StandardUserDataMethodDescriptor mdesc;
- if (m_Methods.TryGetValue(indexName, out mdesc))
- return DynValue.NewCallback(mdesc.GetCallback(script, obj));
- StandardUserDataPropertyDescriptor pdesc;
- if (m_Properties.TryGetValue(indexName, out pdesc))
- {
- object o = pdesc.GetValue(obj);
- return ConversionHelper.ClrObjectToComplexMoonSharpValue(script, o);
- }
- return null;
- }
- public bool SetIndex(Script script, object obj, DynValue index, DynValue value)
- {
- if (index.Type != DataType.String)
- throw ScriptRuntimeException.BadArgument(1, string.Format("userdata<{0}>.__setindex", this.Name), "string", index.Type.ToLuaTypeString(), false);
- bool v = TrySetIndex(script, obj, index.String, value);
- if (!v) v = TrySetIndex(script, obj, UpperFirstLetter(index.String), value);
- if (!v) v = TrySetIndex(script, obj, Camelify(index.String), value);
- if (!v) v = TrySetIndex(script, obj, UpperFirstLetter(Camelify(index.String)), value);
- return v;
- }
- protected virtual bool TrySetIndex(Script script, object obj, string indexName, DynValue value)
- {
- StandardUserDataPropertyDescriptor pdesc;
- if (m_Properties.TryGetValue(indexName, out pdesc))
- {
- object o = ConversionHelper.MoonSharpValueToObjectOfType(value, pdesc.PropertyInfo.PropertyType, null);
- pdesc.SetValue(obj, o, value.Type);
- return true;
- }
- else
- {
- return false;
- }
- }
- internal void Optimize()
- {
- foreach (var m in this.m_Methods.Values)
- m.Optimize();
- foreach (var m in this.m_Properties.Values)
- {
- m.OptimizeGetter();
- m.OptimizeSetter();
- }
- }
- protected static string Camelify(string name)
- {
- StringBuilder sb = new StringBuilder(name.Length);
- bool lastWasUnderscore = false;
- for (int i = 0; i < name.Length; i++)
- {
- if (name[i] == '_' && i != 0)
- {
- lastWasUnderscore = true;
- }
- else
- {
- if (lastWasUnderscore)
- sb.Append(char.ToUpperInvariant(name[i]));
- else
- sb.Append(name[i]);
- lastWasUnderscore = false;
- }
- }
- return sb.ToString();
- }
- protected static string UpperFirstLetter(string name)
- {
- if (!string.IsNullOrEmpty(name))
- return char.ToUpperInvariant(name[0]) + name.Substring(1);
- return name;
- }
- public string AsString(object obj)
- {
- return (obj != null) ? obj.ToString() : null;
- }
- public DynValue MetaIndex(Script script, object obj, string metaname)
- {
- // TODO: meta access to overloaded operators ?
- return null;
- }
- }
- }
|