您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
139 行
3.6 KiB
139 行
3.6 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
using UnityEngine;
|
|
|
|
namespace RMGUI.GraphView
|
|
{
|
|
// types of port to adapt
|
|
class PortSource<T>
|
|
{
|
|
}
|
|
|
|
// attribute to declare and adapter
|
|
class TypeAdapter : Attribute
|
|
{
|
|
}
|
|
|
|
// TODO: This is a straight port from Canvas2D. I don't think that having to check for types in the assembly using reflection is the way we want to go.
|
|
public class NodeAdapter
|
|
{
|
|
private static List<MethodInfo> s_TypeAdapters;
|
|
private static Dictionary<int, MethodInfo> s_NodeAdapterDictionary;
|
|
|
|
public bool CanAdapt(object a, object b)
|
|
{
|
|
if (a == b)
|
|
return false; // self connections are not permitted
|
|
|
|
if (a == null || b == null)
|
|
return false;
|
|
|
|
MethodInfo mi = GetAdapter(a, b);
|
|
if (mi == null)
|
|
{
|
|
Debug.Log("adapter node not found for: " + a.GetType() + " -> " + b.GetType());
|
|
}
|
|
return mi != null;
|
|
}
|
|
|
|
public bool Connect(object a, object b)
|
|
{
|
|
MethodInfo mi = GetAdapter(a, b);
|
|
if (mi == null)
|
|
{
|
|
Debug.LogError("Attempt to connect 2 unadaptable types: " + a.GetType() + " -> " + b.GetType());
|
|
return false;
|
|
}
|
|
object retVal = mi.Invoke(this, new[] { this, a, b });
|
|
return (bool)retVal;
|
|
}
|
|
|
|
IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly, Type extendedType)
|
|
{
|
|
return assembly.GetTypes()
|
|
.Where(t => t.IsSealed && !t.IsGenericType && !t.IsNested)
|
|
.SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
|
|
.Where(m => m.IsDefined(typeof(ExtensionAttribute), false) && m.GetParameters()[0].ParameterType == extendedType);
|
|
}
|
|
|
|
public MethodInfo GetAdapter(object a, object b)
|
|
{
|
|
if (a == null || b == null)
|
|
return null;
|
|
|
|
if (s_NodeAdapterDictionary == null)
|
|
{
|
|
s_NodeAdapterDictionary = new Dictionary<int, MethodInfo>();
|
|
|
|
// add extension methods
|
|
AppDomain currentDomain = AppDomain.CurrentDomain;
|
|
foreach (Assembly assembly in currentDomain.GetAssemblies())
|
|
{
|
|
foreach (MethodInfo method in GetExtensionMethods(assembly, typeof(NodeAdapter)))
|
|
{
|
|
var methodParams = method.GetParameters();
|
|
if (methodParams.Length == 3)
|
|
{
|
|
string pa = methodParams[1].ParameterType + methodParams[2].ParameterType.ToString();
|
|
s_NodeAdapterDictionary.Add(pa.GetHashCode(), method);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
string s = a.GetType().ToString() + b.GetType();
|
|
|
|
MethodInfo methodInfo;
|
|
return s_NodeAdapterDictionary.TryGetValue(s.GetHashCode(), out methodInfo) ? methodInfo : null;
|
|
}
|
|
|
|
public MethodInfo GetTypeAdapter(Type from, Type to)
|
|
{
|
|
if (s_TypeAdapters == null)
|
|
{
|
|
s_TypeAdapters = new List<MethodInfo>();
|
|
AppDomain currentDomain = AppDomain.CurrentDomain;
|
|
foreach (Assembly assembly in currentDomain.GetAssemblies())
|
|
{
|
|
try
|
|
{
|
|
foreach (Type temptype in assembly.GetTypes())
|
|
{
|
|
MethodInfo[] methodInfos = temptype.GetMethods(BindingFlags.Public | BindingFlags.Static);
|
|
foreach (MethodInfo i in methodInfos)
|
|
{
|
|
object[] allAttrs = i.GetCustomAttributes(typeof(TypeAdapter), false);
|
|
if (allAttrs.Any())
|
|
{
|
|
s_TypeAdapters.Add(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.Log(ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
foreach (MethodInfo i in s_TypeAdapters)
|
|
{
|
|
if (i.ReturnType == to)
|
|
{
|
|
ParameterInfo[] allParams = i.GetParameters();
|
|
if (allParams.Length == 1)
|
|
{
|
|
if (allParams[0].ParameterType == from)
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|