/// <summary> /// Calls <see cref="AddStObjMap(IServiceCollection, IActivityMonitor, IStObjMap, SimpleServiceContainer)"/> after /// having obtained the map with <see cref="StObjContextRoot.Load(Assembly, IActivityMonitor)"/>. /// <para> /// Assembly load conflicts may occur here. In such case, you should use the CK.WeakAssemblyNameResolver package /// and wrap the call this way: /// <code> /// using( CK.Core.WeakAssemblyNameResolver.TemporaryInstall() ) /// { /// services.AddStObjMap( "CK.StObj.AutoAssembly" ); /// } /// </code> /// Note that there SHOULD NOT be any conflicts. This workaround may be necessary but hides a conflict of version dependencies /// that may cause runtime errors. /// </para> /// <para> /// If the registration fails for any reason (file not found, type conflicts, etc.), an <see cref="InvalidOperationException"/> is thrown. /// </para> /// </summary> /// <param name="services">This services.</param> /// <param name="monitor">Monitor to use.</param> /// <param name="assemblyName">The assembly name (with or without '.dll' or '.exe' suffix).</param> /// <param name="startupServices"> /// Optional simple container that may provide startup services. This is not used to build IRealObject /// (they must be independent of any "dynamic" services), however registered services become available to /// any <see cref="StObjContextRoot.ConfigureServicesMethodName"/> methods by parameter injection. /// </param> /// <returns>This services collection.</returns> public static IServiceCollection AddStObjMap(this IServiceCollection services, IActivityMonitor monitor, string assemblyName, SimpleServiceContainer?startupServices = null) { var map = StObjContextRoot.Load(assemblyName, monitor); if (map == null) { throw new ArgumentException($"The assembly '{assemblyName}' was not found or is not a valid generated assembly."); } return(AddStObjMap(services, monitor, map, startupServices)); }
/// <summary> /// Loads the <see cref="IStObjMap"/> from <see cref="IRunningBinPathGroup.RunSignature"/> SHA1 from /// already available maps (see <see cref="StObjContextRoot.Load(SHA1Value, IActivityMonitor?)"/>) /// or from the <see cref="IRunningBinPathGroup.GeneratedAssembly"/>. /// <para> /// This must not be called on the <see cref="IRunningBinPathGroup.IsUnifiedPure"/> otherwise an <see cref="InvalidOperationException"/> /// is thrown. /// </para> /// </summary> /// <param name="g">This group from which the map must be obtain.</param> /// <param name="embeddedIfPossible"> /// False to skip an available map and load it from the generated assembly. /// By default, the map is searched in available ones before loading the assembly. /// </param> /// <returns>The map.</returns> public static IStObjMap LoadStObjMap(this IRunningBinPathGroup g, bool embeddedIfPossible = true) { Throw.CheckState(!g.IsUnifiedPure); IStObjMap?map = null; if (embeddedIfPossible) { IStObjMap?embedded = StObjContextRoot.Load(g.RunSignature, TestHelper.Monitor); if (embedded != null) { TestHelper.Monitor.Info(embedded == null ? "No embedded generated source code." : "Embedded generated source code is available."); } } if (map == null) { g.GeneratedAssembly.Exists().Should().BeTrue($"The assembly '{g.GeneratedAssembly.Path}' should have been generated."); var a = AssemblyLoadContext.Default.LoadFromAssemblyPath(g.GeneratedAssembly.Path); map = StObjContextRoot.Load(a, TestHelper.Monitor); map.Should().NotBeNull($"The assembly '{g.GeneratedAssembly.Path}' should be loadable."); } return(map !); }