private static void LoadInMemoryAssemblyInContextImpl(IntPtr moduleHandle, IntPtr assemblyPath, AssemblyLoadContext?alc = null) { string?assemblyPathString = Marshal.PtrToStringUni(assemblyPath); if (assemblyPathString == null) { throw new ArgumentOutOfRangeException(nameof(assemblyPath)); } // We don't cache the ALCs or resolvers here since each IJW assembly will call this method at most once // (the load process rewrites the stubs that call here to call the actual methods they're supposed to) if (alc is null) { alc = new IsolatedComponentLoadContext(assemblyPathString); } else if (alc == AssemblyLoadContext.Default) { var resolver = new AssemblyDependencyResolver(assemblyPathString); AssemblyLoadContext.Default.Resolving += [RequiresUnreferencedCode("C++/CLI is not trim-compatible", Url = "https://aka.ms/dotnet-illink/nativehost")] (context, assemblyName) => { string?assemblyPath = resolver.ResolveAssemblyToPath(assemblyName); return(assemblyPath != null ? context.LoadFromAssemblyPath(assemblyPath) : null); }; } alc.LoadFromInMemoryModule(moduleHandle); }
/// <summary> /// Loads into an isolated AssemblyLoadContext an assembly that has already been loaded into memory by the OS loader as a native module. /// </summary> /// <param name="moduleHandle">The native module handle for the assembly.</param> /// <param name="assemblyPath">The path to the assembly (as a pointer to a UTF-16 C string).</param> public static unsafe void LoadInMemoryAssembly(IntPtr moduleHandle, IntPtr assemblyPath) { // We don't cache the ALCs here since each IJW assembly will call this method at most once // (the load process rewrites the stubs that call here to call the actual methods they're supposed to) AssemblyLoadContext context = new IsolatedComponentLoadContext(Marshal.PtrToStringUni(assemblyPath)); context.LoadFromInMemoryModule(moduleHandle); }
private static IsolatedComponentLoadContext GetIsolatedComponentLoadContext(string assemblyPath) { IsolatedComponentLoadContext?alc; lock (s_assemblyLoadContexts) { if (!s_assemblyLoadContexts.TryGetValue(assemblyPath, out alc)) { alc = new IsolatedComponentLoadContext(assemblyPath); s_assemblyLoadContexts.Add(assemblyPath, alc); } } return(alc); }
public static unsafe void LoadInMemoryAssembly(IntPtr moduleHandle, IntPtr assemblyPath) { string?assemblyPathString = Marshal.PtrToStringUni(assemblyPath); if (assemblyPathString == null) { throw new ArgumentOutOfRangeException(nameof(assemblyPath)); } // We don't cache the ALCs here since each IJW assembly will call this method at most once // (the load process rewrites the stubs that call here to call the actual methods they're supposed to) AssemblyLoadContext context = new IsolatedComponentLoadContext(assemblyPathString); context.LoadFromInMemoryModule(moduleHandle); }
private static Delegate CreateDelegate(string assemblyPath, string typeName, string methodName, string delegateTypeName) { // Throws IsolatedComponentLoadContext alc = GetIsolatedComponentLoadContext(assemblyPath); Func <AssemblyName, Assembly> resolver = name => alc.LoadFromAssemblyName(name); // Throws Type type = Type.GetType(typeName, resolver, null, throwOnError: true) !; // Throws Type delegateType = Type.GetType(delegateTypeName, resolver, null, throwOnError: true) !; // Throws return(Delegate.CreateDelegate(delegateType, type, methodName) !); }
/// <summary> /// Loads into an isolated AssemblyLoadContext an assembly that has already been loaded into memory by the OS loader as a native module. /// </summary> /// <param name="moduleHandle">The native module handle for the assembly.</param> /// <param name="assemblyPath">The path to the assembly (as a pointer to a UTF-16 C string).</param> public static unsafe void LoadInMemoryAssembly(IntPtr moduleHandle, IntPtr assemblyPath) { #if TARGET_WINDOWS if (!IsSupported) { throw new NotSupportedException("This API is not enabled in trimmed scenarios. see https://aka.ms/dotnet-illink/nativehost for more details"); } string?assemblyPathString = Marshal.PtrToStringUni(assemblyPath); if (assemblyPathString == null) { throw new ArgumentOutOfRangeException(nameof(assemblyPath)); } // We don't cache the ALCs here since each IJW assembly will call this method at most once // (the load process rewrites the stubs that call here to call the actual methods they're supposed to) AssemblyLoadContext context = new IsolatedComponentLoadContext(assemblyPathString); context.LoadFromInMemoryModule(moduleHandle); #else throw new PlatformNotSupportedException(); #endif }
public static unsafe int LoadAssemblyAndGetFunctionPointer(IntPtr assemblyPathNative, IntPtr typeNameNative, IntPtr methodNameNative, IntPtr delegateTypeNative, IntPtr reserved, IntPtr functionHandle) { try { // Load the assembly and create a resolver callback for types. string assemblyPath = MarshalToString(assemblyPathNative, nameof(assemblyPathNative)); IsolatedComponentLoadContext alc = GetIsolatedComponentLoadContext(assemblyPath); Func <AssemblyName, Assembly> resolver = name => alc.LoadFromAssemblyName(name); // Get the requested type. string typeName = MarshalToString(typeNameNative, nameof(typeNameNative)); Type type = Type.GetType(typeName, resolver, null, throwOnError: true) !; // Get the method name on the type. string methodName = MarshalToString(methodNameNative, nameof(methodNameNative)); // Determine the signature of the type. There are 3 possibilities: // * No delegate type was supplied - use the default (i.e. ComponentEntryPoint). // * A sentinel value was supplied - the function is marked UnmanagedCallersOnly. This means // a function pointer can be returned without creating a delegate. // * A delegate type was supplied - Load the type and create a delegate for that method. Type?delegateType; if (delegateTypeNative == IntPtr.Zero) { delegateType = typeof(ComponentEntryPoint); } else if (delegateTypeNative == (IntPtr)(-1)) { delegateType = null; } else { string delegateTypeName = MarshalToString(delegateTypeNative, nameof(delegateTypeNative)); delegateType = Type.GetType(delegateTypeName, resolver, null, throwOnError: true) !; } if (reserved != IntPtr.Zero) { throw new ArgumentOutOfRangeException(nameof(reserved)); } if (functionHandle == IntPtr.Zero) { throw new ArgumentNullException(nameof(functionHandle)); } IntPtr functionPtr; if (delegateType == null) { // Match search semantics of the CreateDelegate() function below. BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; MethodInfo? methodInfo = type.GetMethod(methodName, bindingFlags); if (methodInfo == null) { throw new MissingMethodException(typeName, methodName); } // Verify the function is properly marked. if (null == methodInfo.GetCustomAttribute <UnmanagedCallersOnlyAttribute>()) { throw new InvalidOperationException(SR.InvalidOperation_FunctionMissingUnmanagedCallersOnly); } functionPtr = methodInfo.MethodHandle.GetFunctionPointer(); } else { Delegate d = Delegate.CreateDelegate(delegateType, type, methodName) !; functionPtr = Marshal.GetFunctionPointerForDelegate(d); lock (s_delegates) { // Keep a reference to the delegate to prevent it from being garbage collected s_delegates[functionPtr] = d; } } *(IntPtr *)functionHandle = functionPtr; } catch (Exception e) { return(e.HResult); } return(0); }