internal Tuple <GeneratedImplementationTypeIdentifier, Type> PregenerateImplementationType ( [NotNull] Type classType, [NotNull] params Type[] interfaceTypes ) { if (!classType.IsAbstract) { throw new ArgumentException ( "The class to activate must be abstract.", nameof(classType) ); } if (!(classType.IsSubclassOf(typeof(NativeLibraryBase)) || classType == typeof(NativeLibraryBase))) { throw new ArgumentException ( $"The base class must be or derive from {nameof(NativeLibraryBase)}.", nameof(classType) ); } if (!interfaceTypes.Any(i => i.IsInterface)) { throw new ArgumentException ( "The interfaces to activate on the class must be an interface type.", nameof(interfaceTypes) ); } // Check if we've already generated a type for this configuration var key = new GeneratedImplementationTypeIdentifier(classType, interfaceTypes, Options); Type generatedType; lock (BuilderLock) { if (TypeCache.TryGetValue(key, out generatedType)) { return(new Tuple <GeneratedImplementationTypeIdentifier, Type>(key, generatedType)); } generatedType = GenerateInterfaceImplementationType(classType, interfaceTypes); TypeCache.TryAdd(key, generatedType); } return(new Tuple <GeneratedImplementationTypeIdentifier, Type>(key, generatedType)); }
/// <summary> /// Generates the implementation type for a given class and interface combination, caching it for later use. /// </summary> /// <typeparam name="TBaseClass">The base class for the implementation to generate.</typeparam> /// <typeparam name="TInterface">The interface to implement.</typeparam> /// <exception cref="ArgumentException">Thrown if either of the type arguments are incompatible.</exception> /// <exception cref="FileNotFoundException"> /// Thrown if the specified library can't be found in any of the loader paths. /// </exception> internal void PregenerateImplementationType <TBaseClass, TInterface>() where TBaseClass : NativeLibraryBase where TInterface : class { var classType = typeof(TBaseClass); if (!classType.IsAbstract) { throw new ArgumentException ( "The class to activate must be abstract.", nameof(TBaseClass) ); } var interfaceType = typeof(TInterface); if (!interfaceType.IsInterface) { throw new ArgumentException ( "The interface to activate on the class must be an interface type.", nameof(TInterface) ); } // Check if we've already generated a type for this configuration var key = new GeneratedImplementationTypeIdentifier(classType, interfaceType, Options); lock (BuilderLock) { if (TypeCache.TryGetValue(key, out var generatedType)) { return; } generatedType = GenerateInterfaceImplementationType <TBaseClass, TInterface>(); TypeCache.TryAdd(key, generatedType); } }
public TClass ActivateClass <TClass, TInterface>([NotNull] string libraryPath) where TClass : NativeLibraryBase where TInterface : class { var classType = typeof(TClass); if (!classType.IsAbstract) { throw new ArgumentException("The class to activate must be abstract.", nameof(TClass)); } var interfaceType = typeof(TInterface); if (!interfaceType.IsInterface) { throw new ArgumentException ( "The interface to activate on the class must be an interface type.", nameof(TInterface) ); } // Check for remapping if (Options.HasFlagFast(EnableDllMapSupport)) { libraryPath = new DllMapResolver().MapLibraryName(interfaceType, libraryPath); } // Attempt to resolve a name or path for the given library var resolveResult = PathResolver.Resolve(libraryPath); if (!resolveResult.IsSuccess) { throw new FileNotFoundException ( $"The specified library (\"{libraryPath}\") was not found in any of the loader search paths.", libraryPath, resolveResult.Exception ); } libraryPath = resolveResult.Path; // Check if we've already generated a type for this configuration var key = new GeneratedImplementationTypeIdentifier(classType, interfaceType, libraryPath, Options); if (!TypeCache.TryGetValue(key, out var generatedType)) { lock (BuilderLock) { generatedType = GenerateInterfaceImplementationType <TClass, TInterface>(); TypeCache.TryAdd(key, generatedType); } } try { var anonymousInstance = CreateAnonymousImplementationInstance <TInterface> ( generatedType, libraryPath, Options, TransformerRepository ); return(anonymousInstance as TClass ?? throw new InvalidOperationException ( "The resulting instance was not convertible to an instance of the class." )); } catch (TargetInvocationException tex) { if (tex.InnerException is null) { throw; } // Unwrap target invocation exceptions, since we can fail in the constructor throw tex.InnerException; } }
public object ActivateClass ( [NotNull] string libraryPath, [NotNull] Type baseClassType, [NotNull] params Type[] interfaceTypes ) { if (!baseClassType.IsAbstract) { throw new ArgumentException("The class to activate must be abstract.", nameof(baseClassType)); } if (!interfaceTypes.Any(i => i.IsInterface)) { throw new ArgumentException ( "The interfaces to activate on the class must be an interface type.", nameof(interfaceTypes) ); } // Attempt to resolve a name or path for the given library var resolveResult = PathResolver.Resolve(libraryPath); if (!resolveResult.IsSuccess) { throw new FileNotFoundException ( $"The specified library (\"{libraryPath}\") was not found in any of the loader search paths.", libraryPath, resolveResult.Exception ); } libraryPath = resolveResult.Path; // Check if we've already generated a type for this configuration var key = new GeneratedImplementationTypeIdentifier(baseClassType, interfaceTypes, Options); lock (BuilderLock) { if (!TypeCache.TryGetValue(key, out var generatedType)) { generatedType = GenerateInterfaceImplementationType(baseClassType, interfaceTypes); TypeCache.TryAdd(key, generatedType); } try { var anonymousInstance = CreateAnonymousImplementationInstance ( generatedType, libraryPath, Options ); return(anonymousInstance); } catch (TargetInvocationException tex) { if (tex.InnerException is null) { throw; } // Unwrap target invocation exceptions, since we can fail in the constructor throw tex.InnerException; } } }