| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- using System.Text;
- using System.Threading;
- using MoonSharp.Interpreter.Diagnostics;
- namespace MoonSharp.Interpreter.Interop
- {
- internal class UserDataPropertyDescriptor
- {
- internal PropertyInfo PropertyInfo { get; private set; }
- internal InteropAccessMode AccessMode { get; private set; }
- internal bool IsStatic { get; private set; }
- internal string Name { get; private set; }
- Func<object, object> m_OptimizedGetter = null;
- Action<object, object> m_OptimizedSetter = null;
- internal UserDataPropertyDescriptor(PropertyInfo pi, InteropAccessMode accessMode)
- {
- this.PropertyInfo = pi;
- this.AccessMode = accessMode;
- this.Name = pi.Name;
- this.IsStatic = (this.PropertyInfo.GetGetMethod() ?? this.PropertyInfo.GetSetMethod()).IsStatic;
- if (AccessMode == InteropAccessMode.Preoptimized)
- {
- this.OptimizeGetter();
- this.OptimizeSetter();
- }
- }
- internal object GetValue(object obj)
- {
- if (AccessMode == InteropAccessMode.LazyOptimized && m_OptimizedGetter == null)
- OptimizeGetter();
- if (m_OptimizedGetter != null)
- return m_OptimizedGetter(obj);
- return PropertyInfo.GetValue(IsStatic ? null : obj, null);
- }
- internal void OptimizeGetter()
- {
- using (PerformanceStatistics.StartGlobalStopwatch(PerformanceCounter.AdaptersCompilation))
- {
- if (PropertyInfo.CanRead)
- {
- if (IsStatic)
- {
- var paramExp = Expression.Parameter(typeof(object), "dummy");
- var propAccess = Expression.Property(null, PropertyInfo);
- var castPropAccess = Expression.Convert(propAccess, typeof(object));
- var lambda = Expression.Lambda<Func<object, object>>(castPropAccess, paramExp);
- Interlocked.Exchange(ref m_OptimizedGetter, lambda.Compile());
- }
- else
- {
- var paramExp = Expression.Parameter(typeof(object), "obj");
- var castParamExp = Expression.Convert(paramExp, this.PropertyInfo.DeclaringType);
- var propAccess = Expression.Property(castParamExp, PropertyInfo);
- var castPropAccess = Expression.Convert(propAccess, typeof(object));
- var lambda = Expression.Lambda<Func<object, object>>(castPropAccess, paramExp);
- Interlocked.Exchange(ref m_OptimizedGetter, lambda.Compile());
- }
- }
- }
- }
- internal void OptimizeSetter()
- {
- using (PerformanceStatistics.StartGlobalStopwatch(PerformanceCounter.AdaptersCompilation))
- {
- if (PropertyInfo.CanWrite)
- {
- MethodInfo setterMethod = PropertyInfo.GetSetMethod();
- if (IsStatic)
- {
- var paramExp = Expression.Parameter(typeof(object), "dummy");
- var paramValExp = Expression.Parameter(typeof(object), "val");
- var castParamValExp = Expression.Convert(paramValExp, this.PropertyInfo.PropertyType);
- var callExpression = Expression.Call(setterMethod, castParamValExp);
- var lambda = Expression.Lambda<Action<object, object>>(callExpression, paramExp, paramValExp);
- Interlocked.Exchange(ref m_OptimizedSetter, lambda.Compile());
- }
- else
- {
- var paramExp = Expression.Parameter(typeof(object), "obj");
- var paramValExp = Expression.Parameter(typeof(object), "val");
- var castParamExp = Expression.Convert(paramExp, this.PropertyInfo.DeclaringType);
- var castParamValExp = Expression.Convert(paramValExp, this.PropertyInfo.PropertyType);
- var callExpression = Expression.Call(castParamExp, setterMethod, castParamValExp);
- var lambda = Expression.Lambda<Action<object, object>>(callExpression, paramExp, paramValExp);
- Interlocked.Exchange(ref m_OptimizedSetter, lambda.Compile());
- }
- }
- }
- }
- internal void SetValue(object obj, object value, DataType originalType)
- {
- try
- {
- if (value is double)
- value = ConversionHelper.DoubleToType(PropertyInfo.PropertyType, (double)value);
- if (AccessMode == InteropAccessMode.LazyOptimized && m_OptimizedSetter == null)
- OptimizeSetter();
- if (m_OptimizedSetter != null)
- {
- m_OptimizedSetter(obj, value);
- }
- else
- {
- PropertyInfo.SetValue(IsStatic ? null : obj, value, null);
- }
- }
- catch (ArgumentException)
- {
- // non-optimized setters fall here
- throw ScriptRuntimeException.UserDataArgumentTypeMismatch(originalType, PropertyInfo.PropertyType);
- }
- catch (InvalidCastException)
- {
- // optimized setters fall here
- throw ScriptRuntimeException.UserDataArgumentTypeMismatch(originalType, PropertyInfo.PropertyType);
- }
- }
- }
- }
|