@ -10,24 +10,41 @@ using TNodeCore.Runtime.Models;
using UnityEngine ;
using UnityEngine ;
namespace TNodeCore.Runtime.RuntimeCache {
namespace TNodeCore.Runtime.RuntimeCache {
public class Prop Accessor < T1 , T2 > : IModelPr ope rty Accessor {
public class Port Accessor < T1 , T2 > : IModelPortAccessor {
public readonly Func < T1 , T2 > Get ;
public readonly Func < T1 , T2 > Get ;
public readonly Action < T1 , T2 > Set ;
public readonly Action < T1 , T2 > Set ;
public PropAccessor ( string propName ) {
public PortAccessor ( string name , bool property ) {
Type t = typeof ( T1 ) ;
if ( property ) {
Type t = typeof ( T1 ) ;
MethodInfo getter = t . GetMethod ( "get_" + propName ) ;
MethodInfo getter = t . GetMethod ( "get_" + name ) ;
MethodInfo setter = t . GetMethod ( "set_" + propName ) ;
MethodInfo setter = t . GetMethod ( "set_" + name ) ;
Type = getter ? . ReturnType ? ? setter ? . GetParameters ( ) [ 0 ] . ParameterType ;
Type = getter ? . ReturnType ? ? setter ? . GetParameters ( ) [ 0 ] . ParameterType ;
if ( getter ! = null )
if ( getter ! = null )
Get = ( Func < T1 , T2 > ) Delegate . CreateDelegate ( typeof ( Func < T1 , T2 > ) , null , getter ) ;
Get = ( Func < T1 , T2 > ) Delegate . CreateDelegate ( typeof ( Func < T1 , T2 > ) , null , getter ) ;
if ( setter ! = null )
if ( setter ! = null )
Set = ( Action < T1 , T2 > ) Delegate . CreateDelegate ( typeof ( Action < T1 , T2 > ) , null , setter ) ;
Set = ( Action < T1 , T2 > ) Delegate . CreateDelegate ( typeof ( Action < T1 , T2 > ) , null , setter ) ;
}
}
public static PropAccessor < T1 , T2 > Create ( string propName ) {
else {
return new PropAccessor < T1 , T2 > ( propName ) ;
Type t = typeof ( T1 ) ;
MethodInfo method = t . GetMethod ( name ) ;
if ( method = = null ) {
throw new Exception ( "Method not found for name " + name ) ;
}
if ( method . ReturnType ! = typeof ( void ) ) {
Type = method . ReturnType ;
Get = ( Func < T1 , T2 > ) Delegate . CreateDelegate ( typeof ( Func < T1 , T2 > ) , null , method ) ;
}
else {
Type = method . GetParameters ( ) [ 0 ] . ParameterType ;
Set = ( Action < T1 , T2 > ) Delegate . CreateDelegate ( typeof ( Action < T1 , T2 > ) , null , method ) ;
}
}
}
}
public object GetValue ( object model ) {
public object GetValue ( object model ) {
return Get ( ( T1 ) model ) ;
return Get ( ( T1 ) model ) ;
}
}
@ -38,39 +55,9 @@ namespace TNodeCore.Runtime.RuntimeCache{
public Type Type { get ; set ; }
public Type Type { get ; set ; }
}
}
public class MethodAccessorInput < T1 , T2 > : IMethodAccessorInput {
public readonly Action < T1 , T2 > Set ;
public MethodAccessorInput ( string methodName ) {
Type t = typeof ( T1 ) ;
MethodInfo setter = t . GetMethod ( methodName ) ;
if ( setter ! = null )
Set = ( Action < T1 , T2 > ) Delegate . CreateDelegate ( typeof ( Action < T1 , T2 > ) , null , setter ) ;
}
public void SetValue ( object model , object value ) {
Set ( ( T1 ) model , ( T2 ) value ) ;
}
}
public class MethodAccessorOutput < T1 , T2 > : IMethodAccessorOutput {
public readonly Func < T1 , T2 > Get ;
public MethodAccessorOutput ( string methodName ) {
Type t = typeof ( T1 ) ;
MethodInfo getter = t . GetMethod ( methodName ) ;
if ( getter ! = null )
Get = ( Func < T1 , T2 > ) Delegate . CreateDelegate ( typeof ( Func < T1 , T2 > ) , null , getter ) ;
}
public object GetValue ( object model ) {
return Get ( ( T1 ) model ) ;
}
}
public interface IMethodAccessorInput {
public void SetValue ( object model , object o ) ;
}
internal class PortConverterHelper < T1 , T2 > : IPortConverterHelper {
internal class PortConverterHelper < T1 , T2 > : IPortConverterHelper {
private readonly PortTypeConversion < T1 , T2 > _ converter ;
private readonly PortTypeConversion < T1 , T2 > _ converter ;
@ -122,13 +109,9 @@ namespace TNodeCore.Runtime.RuntimeCache{
new Dictionary < Type , Dictionary < string , GetValueDelegate > > ( ) ;
new Dictionary < Type , Dictionary < string , GetValueDelegate > > ( ) ;
public readonly Dictionary < Type , Dictionary < string , SetValueDelegate > > CachedDelegatesForSettingValue =
public readonly Dictionary < Type , Dictionary < string , SetValueDelegate > > CachedDelegatesForSettingValue =
new Dictionary < Type , Dictionary < string , SetValueDelegate > > ( ) ;
new Dictionary < Type , Dictionary < string , SetValueDelegate > > ( ) ;
public readonly Dictionary < Type , Dictionary < string , IModelPropertyAccessor > > CachedPropertyAccessors =
public readonly Dictionary < Type , Dictionary < string , IModelPortAccessor > > CachedPortAccessors =
new Dictionary < Type , Dictionary < string , IModelPropertyAccessor > > ( ) ;
new Dictionary < Type , Dictionary < string , IModelPortAccessor > > ( ) ;
public readonly Dictionary < Type , Dictionary < string , IMethodAccessorInput > > InputMethodPorts = new Dictionary < Type , Dictionary < string , IMethodAccessorInput > > ( ) ;
public readonly Dictionary < Type , Dictionary < string , IMethodAccessorOutput > > OutputMethodPorts =
new Dictionary < Type , Dictionary < string , IMethodAccessorOutput > > ( ) ;
/// <summary>
/// <summary>
/// TODO: Converters now work globally, but it should be possible to specify a converter for a specific graph.but it will be too nested.so in current implementation, we will use a global converter.
/// TODO: Converters now work globally, but it should be possible to specify a converter for a specific graph.but it will be too nested.so in current implementation, we will use a global converter.
/// </summary>
/// </summary>
@ -320,44 +303,35 @@ namespace TNodeCore.Runtime.RuntimeCache{
}
}
}
}
//TODO: CACHE IT AS FUNCTION
//TODO: CACHE IT AS FUNCTION
private static IModelPropertyAccessor CreatePropertyCache ( string propName , Type targetType , Type valueType ) {
private static IModelPortAccessor CreatePortCacheForProperty ( string propName , Type targetType , Type valueType ) {
var makeGenericType = typeof ( PropAccessor < , > ) . MakeGenericType ( targetType , valueType ) ;
var makeGenericType = typeof ( PortAccessor < , > ) . MakeGenericType ( targetType , valueType ) ;
var constructor = makeGenericType . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
var constructor = makeGenericType . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( bool ) } ) ;
var instance = constructor ? . Invoke ( new object [ ] { propName } ) ;
var instance = constructor ? . Invoke ( new object [ ] { propName , true } ) ;
return ( IModelPropertyAccessor ) instance ;
return ( IModelPortAccessor ) instance ;
}
}
public static IMethodAccessorInput CreateMethodInputCache ( string methodName , Type targetType , Type inputTypes ) {
private static IModelPortAccessor CreatePortCacheForMethod ( string methodName , Type targetType , Type valueType ) {
var makeGenericType = typeof ( MethodAccessorInput < , > ) . MakeGenericType ( targetType , inputTypes ) ;
var makeGenericType = typeof ( PortAccessor < , > ) . MakeGenericType ( targetType , valueType ) ;
var constructor = makeGenericType . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
var constructor = makeGenericType . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( bool ) } ) ;
var instance = constructor ? . Invoke ( new object [ ] { methodName } ) ;
var instance = constructor ? . Invoke ( new object [ ] { methodName , false } ) ;
return ( IMethodAccessorInput ) instance ;
return ( IModelPortAccessor ) instance ;
}
public static IMethodAccessorOutput CreateMethodOutputCache ( string methodName , Type targetType , Type outputTypes ) {
var makeGenericType = typeof ( MethodAccessorOutput < , > ) . MakeGenericType ( targetType , outputTypes ) ;
var constructor = makeGenericType . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
var instance = constructor ? . Invoke ( new object [ ] { methodName } ) ;
return ( IMethodAccessorOutput ) instance ;
}
}
public void CacheRuntimeNodeData ( Type type ) {
public void CacheRuntimeNodeData ( Type type ) {
if ( type = = null ) return ;
if ( type = = null ) return ;
if ( ! CachedDelegatesForGettingValue . ContainsKey ( type ) ) {
if ( ! CachedDelegatesForGettingValue . ContainsKey ( type ) ) {
CachedDelegatesForGettingValue . Add ( type , new Dictionary < string , GetValueDelegate > ( ) ) ;
CachedDelegatesForGettingValue . Add ( type , new Dictionary < string , GetValueDelegate > ( ) ) ;
CachedDelegatesForSettingValue . Add ( type , new Dictionary < string , SetValueDelegate > ( ) ) ;
CachedDelegatesForSettingValue . Add ( type , new Dictionary < string , SetValueDelegate > ( ) ) ;
CachedPropertyAccessors . Add ( type , new Dictionary < string , IModelPropertyAccessor > ( ) ) ;
CachedPortAccessors . Add ( type , new Dictionary < string , IModelPortAccessor > ( ) ) ;
InputMethodPorts . Add ( type , new Dictionary < string , IMethodAccessorInput > ( ) ) ;
OutputMethodPorts . Add ( type , new Dictionary < string , IMethodAccessorOutput > ( ) ) ;
var properties = type . GetProperties ( ) ;
var properties = type . GetProperties ( ) ;
foreach ( var property in properties ) {
foreach ( var property in properties ) {
var portAttribute = property . GetCustomAttribute < PortAttribute > ( ) ;
var propertyAccessor = CreatePropertyCache ( property . Name , type , property . PropertyType ) ;
if ( portAttribute = = null ) continue ;
CachedPropertyAccessors [ type ] . Add ( property . Name , propertyAccessor ) ;
var propertyAccessor = CreatePortCacheForProperty ( property . Name , type , property . PropertyType ) ;
CachedPortAccessors [ type ] . Add ( property . Name , propertyAccessor ) ;
}
}
//register the fields
//register the fields
var fields = type . GetFields ( ) ;
var fields = type . GetFields ( ) ;
foreach ( var field in fields ) {
foreach ( var field in fields ) {
var getValueDelegate = GetValueDelegateForField ( field ) ;
var getValueDelegate = GetValueDelegateForField ( field ) ;
CachedDelegatesForGettingValue [ type ] . Add ( field . Name , getValueDelegate ) ;
CachedDelegatesForGettingValue [ type ] . Add ( field . Name , getValueDelegate ) ;
if ( field . IsPublic ) {
if ( field . IsPublic ) {
@ -368,24 +342,12 @@ namespace TNodeCore.Runtime.RuntimeCache{
}
}
var methods = type . GetMethods ( ) ;
var methods = type . GetMethods ( ) ;
foreach ( var method in methods ) {
foreach ( var method in methods ) {
//Check if the method has an [Port] attribute
//Check if the method has an [Port] attribute
var portAttribute = method . GetCustomAttribute < PortAttribute > ( ) ;
var portAttribute = method . GetCustomAttribute < PortAttribute > ( ) ;
if ( portAttribute ! = null ) {
if ( portAttribute ! = null ) {
var propertyAccessor = CreatePortCacheForMethod ( method . Name , type , method . ReturnType = = typeof ( void ) ? method . GetParameters ( ) [ 0 ] . ParameterType : method . ReturnType ) ;
//if the port is an input port. cached it as an function of setting value
CachedPortAccessors [ type ] . Add ( method . Name , propertyAccessor ) ;
if ( portAttribute is InputAttribute ) {
var inputMethodAccessor = CreateMethodInputCache ( method . Name , type ,
method . GetParameters ( ) [ 0 ] . ParameterType ) ;
InputMethodPorts [ type ] . Add ( method . Name , inputMethodAccessor ) ;
}
if ( portAttribute is OutputAttribute ) {
var outputMethodAccessor = CreateMethodOutputCache ( method . Name , type ,
method . ReturnType ) ;
OutputMethodPorts [ type ] . Add ( method . Name , outputMethodAccessor ) ;
}
}
}
}
}
@ -418,9 +380,7 @@ namespace TNodeCore.Runtime.RuntimeCache{
}
}
public interface IMethodAccessorOutput {
object GetValue ( object model ) ;
}
public class ImplicitConversionHelper < T1 , T2 > : IPortConverterHelper {
public class ImplicitConversionHelper < T1 , T2 > : IPortConverterHelper {