public static List <Type> ExplodeSimpleMethodBase(SimpleMethodBase methodBase, out Type resType) { var method = methodBase as SimpleMethodInfo; if (method != null) { return(ExplodeSimpleMethodInfo(method, out resType)); } else { var ctor = methodBase as SimpleConstructorInfo; if (ctor != null) { return(ExplodeSimpleConstructorInfo(ctor, out resType)); } else { throw new InvalidOperationException("unrecognised method base"); } } }
// Called from body generated for an imported constructor to tie the managed and unmanaged objects together public void CompleteConstruction(SimpleMethodBase methodBase, object obj, JSContext ctxt) { var type = methodBase.DeclaringType; var ops = FindInteropOps(type); ops.BindUnmanagedAndManagedInstances(obj, ctxt); }
public static List<Type> ExplodeSimpleMethodBase(SimpleMethodBase methodBase, out Type resType) { var method = methodBase as SimpleMethodInfo; if (method != null) return ExplodeSimpleMethodInfo(method, out resType); else { var ctor = methodBase as SimpleConstructorInfo; if (ctor != null) return ExplodeSimpleConstructorInfo(ctor, out resType); else throw new InvalidOperationException("unrecognised method base"); } }
// ---------------------------------------------------------------------- // Imported and Exported methods // ---------------------------------------------------------------------- // Called from body of imported method to redirect to imported method. Method is (possibly an instance // of a polymorphic method) in (possibly an instance of a higher kinded) type. // If method is a constructor: // - the uninitialized managed object has already been created, but is NOT passed as first // argument in args, and is not represented in argTypes. // - function on unmanaged side does not expect any 'this' argument, but will instead create, initialize // and return the new unmanaged object. // - we return a JSContext for the newly created unamanged object // - the calling ctor must then call the best-matching 'importing constructor' to initialize the // managed object, then call CompleteConstruction to associate the managed and unmanaged objects. public object CallImportedMethod(SimpleMethodBase methodBase, string script, params object[] args) { var resType = default(Type); var argTypes = TypeInfo.ExplodeSimpleMethodBase(methodBase, out resType); var argInteropOps = new InteropOps[argTypes.Count]; for (var i = 0; i < argTypes.Count; i++) argInteropOps[i] = FindInteropOps(argTypes[i]); var resInteropOps = resType == null ? null : FindInteropOps(resType); if (args.Length != argInteropOps.Length) throw new InvalidOperationException("mismatched method arity"); // First pass: check if we need to create any Proxied or Keyed counterparts for arguments, and/or // bind any exported instance methods into unmanaged counterpart. for (var i = 0; i < args.Length; i++) { if (argInteropOps[i].NeedsCreate(args[i])) Eval(argInteropOps[i].AppendCreate, sp => argInteropOps[i].BindCreatedInstance(sp, args[i])); if (argInteropOps[i].NeedsInstanceExportsBound(args[i])) BindExportedMethodsOfType(args[i].GetType(), args[i]); } // Second pass: export args, make call, import result Action<StringBuilder, Dictionary<Type, int>> makeCall = (sb, toBeLoaded) => { sb.Append('('); sb.Append(script); sb.Append(")("); for (var i = 0; i < args.Length; i++) { if (i > 0) sb.Append(','); argInteropOps[i].AppendExport (sb, toBeLoaded, args[i]); } sb.Append(')'); if (resType == null) sb.Append(';'); }; if (resType == null) return Eval(makeCall, null); else return Eval (resInteropOps.WrapImport(makeCall), sp => { sp.SkipWS(); if (methodBase is SimpleConstructorInfo) return resInteropOps.ContextForUnmanagedInstance(sp); else return resInteropOps.Import(sp); }); }