modules/platforms/dotnet/Apache.Ignite/Internal/Compute/Executor/JobLoadContext.cs (36 lines of code) (raw):
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Apache.Ignite.Internal.Compute.Executor;
using System;
using System.Reflection;
using System.Runtime.Loader;
using Ignite.Compute;
/// <summary>
/// Job load context.
/// </summary>
/// <param name="AssemblyLoadContext">Assembly load context.</param>
internal readonly record struct JobLoadContext(AssemblyLoadContext AssemblyLoadContext) : IDisposable
{
/// <summary>
/// Gets or creates a job delegate for the specified type name.
/// </summary>
/// <param name="typeName">Job type name.</param>
/// <returns>Job execution delegate.</returns>
public IComputeJobWrapper CreateJobWrapper(string typeName) =>
CreateJobWrapper(typeName, AssemblyLoadContext);
/// <inheritdoc/>
public void Dispose() => AssemblyLoadContext.Unload();
private static IComputeJobWrapper CreateJobWrapper(string typeName, AssemblyLoadContext ctx)
{
var jobType = LoadJobType(typeName, ctx);
var jobInterface = FindJobInterface(typeName, jobType);
try
{
var genericArgs = jobInterface.GenericTypeArguments;
var jobWrapperType = typeof(ComputeJobWrapper<,,>).MakeGenericType(jobType, genericArgs[0], genericArgs[1]);
return (IComputeJobWrapper)Activator.CreateInstance(jobWrapperType)!;
}
catch (Exception e)
{
if (jobType.GetConstructor(BindingFlags.Public, []) == null)
{
throw new InvalidOperationException($"No public parameterless constructor for job type '{typeName}'", e);
}
throw;
}
}
private static Type LoadJobType(string typeName, AssemblyLoadContext ctx) =>
Type.GetType(typeName, ctx.LoadFromAssemblyName, null)
?? throw new InvalidOperationException($"Type '{typeName}' not found in the specified deployment units.");
// Simple lookup by name. Will throw in a case of ambiguity.
private static Type FindJobInterface(string typeName, Type jobType) =>
jobType.GetInterface(typeof(IComputeJob<,>).Name, ignoreCase: false) ??
throw new InvalidOperationException($"Failed to find job interface '{typeof(IComputeJob<,>)}' in type '{typeName}'");
}