forked from cgvr/DeltaVR
		
	
		
			
				
	
	
		
			155 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			155 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using MonoFN.Cecil;
 | 
						|
using MonoFN.Cecil.Rocks;
 | 
						|
using System;
 | 
						|
 | 
						|
namespace FishNet.CodeGenerating.Helping.Extension
 | 
						|
{
 | 
						|
 | 
						|
    internal static class MethodReferenceExtensions
 | 
						|
    {
 | 
						|
        /// <summary>
 | 
						|
        /// Makes a generic method with specified arguments.
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="method"></param>
 | 
						|
        /// <param name="genericArguments"></param>
 | 
						|
        /// <returns></returns>
 | 
						|
        public static GenericInstanceMethod MakeGenericMethod(this MethodReference method, params TypeReference[] genericArguments)
 | 
						|
        {
 | 
						|
            GenericInstanceMethod result = new GenericInstanceMethod(method);
 | 
						|
            foreach (TypeReference argument in genericArguments)
 | 
						|
                result.GenericArguments.Add(argument);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Makes a generic method with the same arguments as the original.
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="method"></param>
 | 
						|
        /// <returns></returns>
 | 
						|
        public static GenericInstanceMethod MakeGenericMethod(this MethodReference method)
 | 
						|
        {
 | 
						|
            GenericInstanceMethod result = new GenericInstanceMethod(method);
 | 
						|
            foreach (ParameterDefinition pd in method.Parameters)
 | 
						|
                result.GenericArguments.Add(pd.ParameterType);
 | 
						|
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Returns a method reference for a generic method.
 | 
						|
        /// </summary>
 | 
						|
        public static MethodReference GetMethodReference(this MethodReference mr, CodegenSession session, TypeReference typeReference)
 | 
						|
        {
 | 
						|
            return mr.GetMethodReference(session, new TypeReference[] { typeReference });
 | 
						|
        }
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Returns a method reference for a generic method.
 | 
						|
        /// </summary>
 | 
						|
        public static MethodReference GetMethodReference(this MethodReference mr, CodegenSession session, TypeReference[] typeReferences)
 | 
						|
        {
 | 
						|
            if (mr.HasGenericParameters)
 | 
						|
            {
 | 
						|
                if (typeReferences == null || typeReferences.Length == 0)
 | 
						|
                {
 | 
						|
                    session.LogError($"Method {mr.Name} has generic parameters but TypeReferences are null or 0 length.");
 | 
						|
                    return null;
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    GenericInstanceMethod gim = mr.MakeGenericMethod(typeReferences);
 | 
						|
                    return gim;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                return mr;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets a Resolve favoring cached results first.
 | 
						|
        /// </summary>
 | 
						|
        internal static MethodDefinition CachedResolve(this MethodReference methodRef, CodegenSession session)
 | 
						|
        {
 | 
						|
            return session.GetClass<GeneralHelper>().GetMethodReferenceResolve(methodRef);
 | 
						|
        }
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Given a method of a generic class such as ArraySegment`T.get_Count,
 | 
						|
        /// and a generic instance such as ArraySegment`int
 | 
						|
        /// Creates a reference to the specialized method  ArraySegment`int`.get_Count
 | 
						|
        /// <para> Note that calling ArraySegment`T.get_Count directly gives an invalid IL error </para>
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="self"></param>
 | 
						|
        /// <param name="instanceType"></param>
 | 
						|
        /// <returns></returns>
 | 
						|
        public static MethodReference MakeHostInstanceGeneric(this MethodReference self, CodegenSession session, GenericInstanceType instanceType)
 | 
						|
        {
 | 
						|
            MethodReference reference = new MethodReference(self.Name, self.ReturnType, instanceType)
 | 
						|
            {
 | 
						|
                CallingConvention = self.CallingConvention,
 | 
						|
                HasThis = self.HasThis,
 | 
						|
                ExplicitThis = self.ExplicitThis
 | 
						|
            };
 | 
						|
 | 
						|
            foreach (ParameterDefinition parameter in self.Parameters)
 | 
						|
                reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType));
 | 
						|
 | 
						|
            foreach (GenericParameter generic_parameter in self.GenericParameters)
 | 
						|
                reference.GenericParameters.Add(new GenericParameter(generic_parameter.Name, reference));
 | 
						|
 | 
						|
            return session.ImportReference(reference);
 | 
						|
        }
 | 
						|
        /// <summary>
 | 
						|
        /// Given a method of a generic class such as ArraySegment`T.get_Count,
 | 
						|
        /// and a generic instance such as ArraySegment`int
 | 
						|
        /// Creates a reference to the specialized method  ArraySegment`int`.get_Count
 | 
						|
        /// <para> Note that calling ArraySegment`T.get_Count directly gives an invalid IL error </para>
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="self"></param>
 | 
						|
        /// <param name="instanceType"></param>
 | 
						|
        /// <returns></returns>
 | 
						|
        public static MethodReference MakeHostInstanceGeneric(this MethodReference self, TypeReference typeRef, params TypeReference[] args)
 | 
						|
        {
 | 
						|
            GenericInstanceType git = typeRef.MakeGenericInstanceType(args);
 | 
						|
            MethodReference reference = new MethodReference(self.Name, self.ReturnType, git)
 | 
						|
            {
 | 
						|
                CallingConvention = self.CallingConvention,
 | 
						|
                HasThis = self.HasThis,
 | 
						|
                ExplicitThis = self.ExplicitThis
 | 
						|
            };
 | 
						|
 | 
						|
            foreach (ParameterDefinition parameter in self.Parameters)
 | 
						|
                reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType));
 | 
						|
 | 
						|
            foreach (GenericParameter generic_parameter in self.GenericParameters)
 | 
						|
                reference.GenericParameters.Add(new GenericParameter(generic_parameter.Name, reference));
 | 
						|
 | 
						|
            return reference;
 | 
						|
        }
 | 
						|
        public static bool Is<T>(this MethodReference method, string name)
 | 
						|
        {
 | 
						|
            return method.DeclaringType.Is<T>() && method.Name == name;
 | 
						|
        }
 | 
						|
        public static bool Is<T>(this TypeReference td)
 | 
						|
        {
 | 
						|
            return Is(td, typeof(T));
 | 
						|
        }
 | 
						|
 | 
						|
        public static bool Is(this TypeReference td, Type t)
 | 
						|
        {
 | 
						|
            if (t.IsGenericType)
 | 
						|
            {
 | 
						|
                return td.GetElementType().FullName == t.FullName;
 | 
						|
            }
 | 
						|
            return td.FullName == t.FullName;
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
} |