|
|
|
@ -13,6 +13,8 @@ namespace TNodeCore.Runtime.RuntimeCache{ |
|
|
|
|
public class PortAccessor<T1, T2>:IModelPortAccessor{ |
|
|
|
|
public readonly Func<T1, T2> Get; |
|
|
|
|
public readonly Action<T1, T2> Set; |
|
|
|
|
private readonly Action<T1> _resetFunc; |
|
|
|
|
private readonly T2 _defaultValue; |
|
|
|
|
public PortAccessor(string name,bool property){ |
|
|
|
|
if (property){ |
|
|
|
|
Type t = typeof(T1); |
|
|
|
@ -20,10 +22,21 @@ namespace TNodeCore.Runtime.RuntimeCache{ |
|
|
|
|
MethodInfo getter = t.GetMethod("get_" + name); |
|
|
|
|
MethodInfo setter = t.GetMethod("set_" + name); |
|
|
|
|
Type = getter?.ReturnType??setter?.GetParameters()[0].ParameterType; |
|
|
|
|
|
|
|
|
|
if(getter!=null) |
|
|
|
|
Get = (Func<T1, T2>)Delegate.CreateDelegate(typeof(Func<T1, T2>), null, getter); |
|
|
|
|
if(setter!=null) |
|
|
|
|
Set = (Action<T1, T2>)Delegate.CreateDelegate(typeof(Action<T1, T2>), null, setter); |
|
|
|
|
if (Set != null){ |
|
|
|
|
var dummy = Activator.CreateInstance<T1>(); |
|
|
|
|
|
|
|
|
|
if (Get != null) |
|
|
|
|
_defaultValue = Get(dummy); |
|
|
|
|
|
|
|
|
|
_resetFunc += (obj) => { |
|
|
|
|
Set(obj, _defaultValue); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else{ |
|
|
|
|
Type t = typeof(T1); |
|
|
|
@ -46,6 +59,12 @@ namespace TNodeCore.Runtime.RuntimeCache{ |
|
|
|
|
public void SetValue(object model, object value){ |
|
|
|
|
Set((T1)model,(T2)value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void Reset(object model){ |
|
|
|
|
//Get |
|
|
|
|
_resetFunc?.Invoke((T1)model); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Type Type{ get; set; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -214,19 +233,21 @@ namespace TNodeCore.Runtime.RuntimeCache{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void CachingImplicitConversion(Type baseType, Type targetType){ |
|
|
|
|
if (HasImplicitConversion(baseType, targetType)) return; |
|
|
|
|
|
|
|
|
|
if (!HasImplicitConversion(baseType, targetType)) return; |
|
|
|
|
if (CachedPortConverters.ContainsKey(baseType)&&CachedPortConverters[baseType].ContainsKey(targetType)) return; |
|
|
|
|
//Create Implicit Conversion Helper that caches the implicit cast function |
|
|
|
|
var typeConverter = Activator.CreateInstance(typeof(ImplicitConversionHelper<,>).MakeGenericType(baseType, targetType)) as IPortConverterHelper; |
|
|
|
|
|
|
|
|
|
if (!CachedPortConverters.ContainsKey(baseType)){ |
|
|
|
|
CachedPortConverters.Add(baseType,new Dictionary<Type,IPortConverterHelper>()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CachedPortConverters[baseType].Add(targetType,typeConverter); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public object GetConvertedValue(Type from,Type to,object value){ |
|
|
|
|
|
|
|
|
|
if(!CachedPortConverters.ContainsKey(from)){ |
|
|
|
|
//Find the cached port failed ,check if there is an implicit conversion |
|
|
|
|
//This inner cache method would only run once,so add a guard to prevent it run again,even though the function itself has a guard statement. |
|
|
|
@ -384,14 +405,20 @@ namespace TNodeCore.Runtime.RuntimeCache{ |
|
|
|
|
var method = typeof(T2).GetMethod("op_Implicit", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(T1) }, null); |
|
|
|
|
if (method == null){ |
|
|
|
|
//Search it in T1 |
|
|
|
|
method = typeof(T1).GetMethod("op_Implicit", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(T2) }, null); |
|
|
|
|
Debug.Log($"{typeof(T1)}"); |
|
|
|
|
method = typeof(T1).GetMethods(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(x => x.ReturnType==typeof(T2) && x.Name=="op_Implicit"); |
|
|
|
|
} |
|
|
|
|
//Create the delegate |
|
|
|
|
if (method != null) |
|
|
|
|
ConvertFunc = (Func<T1, T2>) Delegate.CreateDelegate(typeof(Func<T1, T2>), method); |
|
|
|
|
if (ConvertFunc == null){ |
|
|
|
|
Debug.Log($"{method==null}"); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public object Convert(object value){ |
|
|
|
|
|
|
|
|
|
return ConvertFunc((T1) value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|