File-scoped namespaces in files under `ComponentModel` (`Microsoft.ML.Core`) (#6788)

Co-authored-by: Lehonti Ramos <john@doe>
This commit is contained in:
Lehonti Ramos 2023-08-31 06:21:19 +02:00 коммит произвёл GitHub
Родитель e3f53a4497
Коммит 34389b63e5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 1628 добавлений и 1633 удалений

Просмотреть файл

@ -8,286 +8,285 @@ using System.IO.Compression;
using System.Reflection;
using Microsoft.ML.Internal.Utilities;
namespace Microsoft.ML.Runtime
namespace Microsoft.ML.Runtime;
[Obsolete("The usage for this is intended for the internal command line utilities and is not intended for anything related to the API. " +
"Please consider another way of doing whatever it is you're attempting to accomplish.")]
[BestFriend]
internal static class AssemblyLoadingUtils
{
[Obsolete("The usage for this is intended for the internal command line utilities and is not intended for anything related to the API. " +
"Please consider another way of doing whatever it is you're attempting to accomplish.")]
[BestFriend]
internal static class AssemblyLoadingUtils
/// <summary>
/// Make sure the given assemblies are loaded and that their loadable classes have been catalogued.
/// </summary>
public static void LoadAndRegister(IHostEnvironment env, string[] assemblies)
{
/// <summary>
/// Make sure the given assemblies are loaded and that their loadable classes have been catalogued.
/// </summary>
public static void LoadAndRegister(IHostEnvironment env, string[] assemblies)
Contracts.AssertValue(env);
if (Utils.Size(assemblies) > 0)
{
Contracts.AssertValue(env);
if (Utils.Size(assemblies) > 0)
foreach (string path in assemblies)
{
foreach (string path in assemblies)
Exception ex = null;
try
{
Exception ex = null;
try
// REVIEW: Will LoadFrom ever return null?
Contracts.CheckNonEmpty(path, nameof(path));
if (!File.Exists(path))
{
// REVIEW: Will LoadFrom ever return null?
Contracts.CheckNonEmpty(path, nameof(path));
if (!File.Exists(path))
{
throw Contracts.ExceptParam(nameof(path), "File does not exist at path: {0}", path);
}
var assem = LoadAssembly(env, path);
if (assem != null)
continue;
throw Contracts.ExceptParam(nameof(path), "File does not exist at path: {0}", path);
}
catch (Exception e)
{
ex = e;
}
// If it is a zip file, load it that way.
ZipArchive zip;
try
{
zip = ZipFile.OpenRead(path);
}
catch (Exception e)
{
// Couldn't load as an assembly and not a zip, so warn the user.
ex = ex ?? e;
Console.Error.WriteLine("Warning: Could not load '{0}': {1}", path, ex.Message);
var assem = LoadAssembly(env, path);
if (assem != null)
continue;
}
string dir;
try
{
dir = CreateTempDirectory();
}
catch (Exception e)
{
throw Contracts.ExceptIO(e, "Creating temp directory for extra assembly zip extraction failed: '{0}'", path);
}
try
{
zip.ExtractToDirectory(dir);
}
catch (Exception e)
{
throw Contracts.ExceptIO(e, "Extracting extra assembly zip failed: '{0}'", path);
}
LoadAssembliesInDir(env, dir, false);
}
}
}
public static IDisposable CreateAssemblyRegistrar(IHostEnvironment env, string loadAssembliesPath = null)
{
Contracts.CheckValue(env, nameof(env));
env.CheckValueOrNull(loadAssembliesPath);
return new AssemblyRegistrar(env, loadAssembliesPath);
}
public static void RegisterCurrentLoadedAssemblies(IHostEnvironment env)
{
Contracts.CheckValue(env, nameof(env));
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
TryRegisterAssembly(env.ComponentCatalog, a);
}
}
private static string CreateTempDirectory()
{
string dir = GetTempPath();
Directory.CreateDirectory(dir);
return dir;
}
private static string GetTempPath()
{
Guid guid = Guid.NewGuid();
return Path.GetFullPath(Path.Combine(Path.GetTempPath(), "MLNET_" + guid.ToString()));
}
private static readonly string[] _filePrefixesToAvoid = new string[] {
"api-ms-win",
"clr",
"coreclr",
"dbgshim",
"ext-ms-win",
"microsoft.bond.",
"microsoft.cosmos.",
"microsoft.csharp",
"microsoft.data.",
"microsoft.hpc.",
"microsoft.live.",
"microsoft.platformbuilder.",
"microsoft.visualbasic",
"microsoft.visualstudio.",
"microsoft.win32",
"microsoft.windowsapicodepack.",
"microsoft.windowsazure.",
"mscor",
"msvc",
"petzold.",
"roslyn.",
"sho",
"sni",
"sqm",
"system.",
"zlib",
};
private static bool ShouldSkipPath(string path)
{
string name = Path.GetFileName(path).ToLowerInvariant();
switch (name)
{
case "cpumathnative.dll":
case "cqo.dll":
case "fasttreenative.dll":
case "libiomp5md.dll":
case "ldanative.dll":
case "libvw.dll":
case "matrixinterf.dll":
case "microsoft.ml.neuralnetworks.gpucuda.dll":
case "mklimports.dll":
case "microsoft.research.controls.decisiontrees.dll":
case "microsoft.ml.neuralnetworks.sse.dll":
case "mklproxynative.dll":
case "neuraltreeevaluator.dll":
case "optimizationbuilderdotnet.dll":
case "parallelcommunicator.dll":
case "Microsoft.ML.runtests.dll":
case "scopecompiler.dll":
case "symsgdnative.dll":
case "tbb.dll":
case "internallearnscope.dll":
case "unmanagedlib.dll":
case "vcclient.dll":
case "libxgboost.dll":
case "zedgraph.dll":
case "__scopecodegen__.dll":
case "cosmosClientApi.dll":
return true;
}
foreach (var s in _filePrefixesToAvoid)
{
if (name.StartsWith(s, StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
}
private static void LoadAssembliesInDir(IHostEnvironment env, string dir, bool filter)
{
if (!Directory.Exists(dir))
return;
// Load all dlls in the given directory.
var paths = Directory.EnumerateFiles(dir, "*.dll");
foreach (string path in paths)
{
if (filter && ShouldSkipPath(path))
catch (Exception e)
{
ex = e;
}
// If it is a zip file, load it that way.
ZipArchive zip;
try
{
zip = ZipFile.OpenRead(path);
}
catch (Exception e)
{
// Couldn't load as an assembly and not a zip, so warn the user.
ex = ex ?? e;
Console.Error.WriteLine("Warning: Could not load '{0}': {1}", path, ex.Message);
continue;
}
LoadAssembly(env, path);
}
}
/// <summary>
/// Given an assembly path, load the assembly and register it with the ComponentCatalog.
/// </summary>
private static Assembly LoadAssembly(IHostEnvironment env, string path)
{
Assembly assembly = null;
try
{
assembly = Assembly.LoadFrom(path);
}
catch (Exception)
{
return null;
}
if (assembly != null)
{
TryRegisterAssembly(env.ComponentCatalog, assembly);
}
return assembly;
}
/// <summary>
/// Checks whether <paramref name="assembly"/> references the assembly containing LoadableClassAttributeBase,
/// and therefore can contain components.
/// </summary>
private static bool CanContainComponents(Assembly assembly)
{
var targetFullName = typeof(LoadableClassAttributeBase).Assembly.GetName().FullName;
bool found = false;
foreach (var name in assembly.GetReferencedAssemblies())
{
if (name.FullName == targetFullName)
string dir;
try
{
found = true;
break;
dir = CreateTempDirectory();
}
}
return found;
}
private static void TryRegisterAssembly(ComponentCatalog catalog, Assembly assembly)
{
// Don't try to index dynamic generated assembly
if (assembly.IsDynamic)
return;
if (!CanContainComponents(assembly))
return;
catalog.RegisterAssembly(assembly);
}
private sealed class AssemblyRegistrar : IDisposable
{
private readonly IHostEnvironment _env;
public AssemblyRegistrar(IHostEnvironment env, string path)
{
_env = env;
RegisterCurrentLoadedAssemblies(_env);
if (!string.IsNullOrEmpty(path))
catch (Exception e)
{
LoadAssembliesInDir(_env, path, true);
path = Path.Combine(path, "AutoLoad");
LoadAssembliesInDir(_env, path, true);
throw Contracts.ExceptIO(e, "Creating temp directory for extra assembly zip extraction failed: '{0}'", path);
}
AppDomain.CurrentDomain.AssemblyLoad += CurrentDomainAssemblyLoad;
}
try
{
zip.ExtractToDirectory(dir);
}
catch (Exception e)
{
throw Contracts.ExceptIO(e, "Extracting extra assembly zip failed: '{0}'", path);
}
public void Dispose()
{
AppDomain.CurrentDomain.AssemblyLoad -= CurrentDomainAssemblyLoad;
}
private void CurrentDomainAssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
TryRegisterAssembly(_env.ComponentCatalog, args.LoadedAssembly);
LoadAssembliesInDir(env, dir, false);
}
}
}
public static IDisposable CreateAssemblyRegistrar(IHostEnvironment env, string loadAssembliesPath = null)
{
Contracts.CheckValue(env, nameof(env));
env.CheckValueOrNull(loadAssembliesPath);
return new AssemblyRegistrar(env, loadAssembliesPath);
}
public static void RegisterCurrentLoadedAssemblies(IHostEnvironment env)
{
Contracts.CheckValue(env, nameof(env));
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
TryRegisterAssembly(env.ComponentCatalog, a);
}
}
private static string CreateTempDirectory()
{
string dir = GetTempPath();
Directory.CreateDirectory(dir);
return dir;
}
private static string GetTempPath()
{
Guid guid = Guid.NewGuid();
return Path.GetFullPath(Path.Combine(Path.GetTempPath(), "MLNET_" + guid.ToString()));
}
private static readonly string[] _filePrefixesToAvoid = new string[] {
"api-ms-win",
"clr",
"coreclr",
"dbgshim",
"ext-ms-win",
"microsoft.bond.",
"microsoft.cosmos.",
"microsoft.csharp",
"microsoft.data.",
"microsoft.hpc.",
"microsoft.live.",
"microsoft.platformbuilder.",
"microsoft.visualbasic",
"microsoft.visualstudio.",
"microsoft.win32",
"microsoft.windowsapicodepack.",
"microsoft.windowsazure.",
"mscor",
"msvc",
"petzold.",
"roslyn.",
"sho",
"sni",
"sqm",
"system.",
"zlib",
};
private static bool ShouldSkipPath(string path)
{
string name = Path.GetFileName(path).ToLowerInvariant();
switch (name)
{
case "cpumathnative.dll":
case "cqo.dll":
case "fasttreenative.dll":
case "libiomp5md.dll":
case "ldanative.dll":
case "libvw.dll":
case "matrixinterf.dll":
case "microsoft.ml.neuralnetworks.gpucuda.dll":
case "mklimports.dll":
case "microsoft.research.controls.decisiontrees.dll":
case "microsoft.ml.neuralnetworks.sse.dll":
case "mklproxynative.dll":
case "neuraltreeevaluator.dll":
case "optimizationbuilderdotnet.dll":
case "parallelcommunicator.dll":
case "Microsoft.ML.runtests.dll":
case "scopecompiler.dll":
case "symsgdnative.dll":
case "tbb.dll":
case "internallearnscope.dll":
case "unmanagedlib.dll":
case "vcclient.dll":
case "libxgboost.dll":
case "zedgraph.dll":
case "__scopecodegen__.dll":
case "cosmosClientApi.dll":
return true;
}
foreach (var s in _filePrefixesToAvoid)
{
if (name.StartsWith(s, StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
}
private static void LoadAssembliesInDir(IHostEnvironment env, string dir, bool filter)
{
if (!Directory.Exists(dir))
return;
// Load all dlls in the given directory.
var paths = Directory.EnumerateFiles(dir, "*.dll");
foreach (string path in paths)
{
if (filter && ShouldSkipPath(path))
{
continue;
}
LoadAssembly(env, path);
}
}
/// <summary>
/// Given an assembly path, load the assembly and register it with the ComponentCatalog.
/// </summary>
private static Assembly LoadAssembly(IHostEnvironment env, string path)
{
Assembly assembly = null;
try
{
assembly = Assembly.LoadFrom(path);
}
catch (Exception)
{
return null;
}
if (assembly != null)
{
TryRegisterAssembly(env.ComponentCatalog, assembly);
}
return assembly;
}
/// <summary>
/// Checks whether <paramref name="assembly"/> references the assembly containing LoadableClassAttributeBase,
/// and therefore can contain components.
/// </summary>
private static bool CanContainComponents(Assembly assembly)
{
var targetFullName = typeof(LoadableClassAttributeBase).Assembly.GetName().FullName;
bool found = false;
foreach (var name in assembly.GetReferencedAssemblies())
{
if (name.FullName == targetFullName)
{
found = true;
break;
}
}
return found;
}
private static void TryRegisterAssembly(ComponentCatalog catalog, Assembly assembly)
{
// Don't try to index dynamic generated assembly
if (assembly.IsDynamic)
return;
if (!CanContainComponents(assembly))
return;
catalog.RegisterAssembly(assembly);
}
private sealed class AssemblyRegistrar : IDisposable
{
private readonly IHostEnvironment _env;
public AssemblyRegistrar(IHostEnvironment env, string path)
{
_env = env;
RegisterCurrentLoadedAssemblies(_env);
if (!string.IsNullOrEmpty(path))
{
LoadAssembliesInDir(_env, path, true);
path = Path.Combine(path, "AutoLoad");
LoadAssembliesInDir(_env, path, true);
}
AppDomain.CurrentDomain.AssemblyLoad += CurrentDomainAssemblyLoad;
}
public void Dispose()
{
AppDomain.CurrentDomain.AssemblyLoad -= CurrentDomainAssemblyLoad;
}
private void CurrentDomainAssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
TryRegisterAssembly(_env.ComponentCatalog, args.LoadedAssembly);
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -4,166 +4,165 @@
using System;
namespace Microsoft.ML.Runtime
namespace Microsoft.ML.Runtime;
/// <summary>
/// This is a token interface that all component factories must implement.
/// </summary>
public interface IComponentFactory
{
}
/// <summary>
/// An interface for creating a component with no extra parameters (other than an <see cref="IHostEnvironment"/>).
/// </summary>
public interface IComponentFactory<out TComponent> : IComponentFactory
{
TComponent CreateComponent(IHostEnvironment env);
}
/// <summary>
/// An interface for creating a component when we take one extra parameter (and an <see cref="IHostEnvironment"/>).
/// </summary>
public interface IComponentFactory<in TArg1, out TComponent> : IComponentFactory
{
TComponent CreateComponent(IHostEnvironment env, TArg1 argument1);
}
/// <summary>
/// An interface for creating a component when we take two extra parameters (and an <see cref="IHostEnvironment"/>).
/// </summary>
public interface IComponentFactory<in TArg1, in TArg2, out TComponent> : IComponentFactory
{
TComponent CreateComponent(IHostEnvironment env, TArg1 argument1, TArg2 argument2);
}
/// <summary>
/// An interface for creating a component when we take three extra parameters (and an <see cref="IHostEnvironment"/>).
/// </summary>
public interface IComponentFactory<in TArg1, in TArg2, in TArg3, out TComponent> : IComponentFactory
{
TComponent CreateComponent(IHostEnvironment env, TArg1 argument1, TArg2 argument2, TArg3 argument3);
}
/// <summary>
/// A utility class for creating <see cref="IComponentFactory"/> instances.
/// </summary>
[BestFriend]
internal static class ComponentFactoryUtils
{
/// <summary>
/// This is a token interface that all component factories must implement.
/// Creates a component factory with no extra parameters (other than an <see cref="IHostEnvironment"/>)
/// that simply wraps a delegate which creates the component.
/// </summary>
public interface IComponentFactory
public static IComponentFactory<TComponent> CreateFromFunction<TComponent>(Func<IHostEnvironment, TComponent> factory)
{
return new SimpleComponentFactory<TComponent>(factory);
}
/// <summary>
/// An interface for creating a component with no extra parameters (other than an <see cref="IHostEnvironment"/>).
/// Creates a component factory when we take one extra parameter (and an
/// <see cref="IHostEnvironment"/>) that simply wraps a delegate which creates the component.
/// </summary>
public interface IComponentFactory<out TComponent> : IComponentFactory
public static IComponentFactory<TArg1, TComponent> CreateFromFunction<TArg1, TComponent>(Func<IHostEnvironment, TArg1, TComponent> factory)
{
TComponent CreateComponent(IHostEnvironment env);
return new SimpleComponentFactory<TArg1, TComponent>(factory);
}
/// <summary>
/// An interface for creating a component when we take one extra parameter (and an <see cref="IHostEnvironment"/>).
/// Creates a component factory when we take two extra parameters (and an
/// <see cref="IHostEnvironment"/>) that simply wraps a delegate which creates the component.
/// </summary>
public interface IComponentFactory<in TArg1, out TComponent> : IComponentFactory
public static IComponentFactory<TArg1, TArg2, TComponent> CreateFromFunction<TArg1, TArg2, TComponent>(Func<IHostEnvironment, TArg1, TArg2, TComponent> factory)
{
TComponent CreateComponent(IHostEnvironment env, TArg1 argument1);
return new SimpleComponentFactory<TArg1, TArg2, TComponent>(factory);
}
/// <summary>
/// An interface for creating a component when we take two extra parameters (and an <see cref="IHostEnvironment"/>).
/// Creates a component factory when we take three extra parameters (and an
/// <see cref="IHostEnvironment"/>) that simply wraps a delegate which creates the component.
/// </summary>
public interface IComponentFactory<in TArg1, in TArg2, out TComponent> : IComponentFactory
public static IComponentFactory<TArg1, TArg2, TArg3, TComponent> CreateFromFunction<TArg1, TArg2, TArg3, TComponent>(Func<IHostEnvironment, TArg1, TArg2, TArg3, TComponent> factory)
{
TComponent CreateComponent(IHostEnvironment env, TArg1 argument1, TArg2 argument2);
return new SimpleComponentFactory<TArg1, TArg2, TArg3, TComponent>(factory);
}
/// <summary>
/// An interface for creating a component when we take three extra parameters (and an <see cref="IHostEnvironment"/>).
/// A class for creating a component with no extra parameters (other than an <see cref="IHostEnvironment"/>)
/// that simply wraps a delegate which creates the component.
/// </summary>
public interface IComponentFactory<in TArg1, in TArg2, in TArg3, out TComponent> : IComponentFactory
private sealed class SimpleComponentFactory<TComponent> : IComponentFactory<TComponent>
{
TComponent CreateComponent(IHostEnvironment env, TArg1 argument1, TArg2 argument2, TArg3 argument3);
private readonly Func<IHostEnvironment, TComponent> _factory;
public SimpleComponentFactory(Func<IHostEnvironment, TComponent> factory)
{
_factory = factory;
}
public TComponent CreateComponent(IHostEnvironment env)
{
return _factory(env);
}
}
/// <summary>
/// A utility class for creating <see cref="IComponentFactory"/> instances.
/// A class for creating a component when we take one extra parameter
/// (and an <see cref="IHostEnvironment"/>) that simply wraps a delegate which
/// creates the component.
/// </summary>
[BestFriend]
internal static class ComponentFactoryUtils
private sealed class SimpleComponentFactory<TArg1, TComponent> : IComponentFactory<TArg1, TComponent>
{
/// <summary>
/// Creates a component factory with no extra parameters (other than an <see cref="IHostEnvironment"/>)
/// that simply wraps a delegate which creates the component.
/// </summary>
public static IComponentFactory<TComponent> CreateFromFunction<TComponent>(Func<IHostEnvironment, TComponent> factory)
private readonly Func<IHostEnvironment, TArg1, TComponent> _factory;
public SimpleComponentFactory(Func<IHostEnvironment, TArg1, TComponent> factory)
{
return new SimpleComponentFactory<TComponent>(factory);
_factory = factory;
}
/// <summary>
/// Creates a component factory when we take one extra parameter (and an
/// <see cref="IHostEnvironment"/>) that simply wraps a delegate which creates the component.
/// </summary>
public static IComponentFactory<TArg1, TComponent> CreateFromFunction<TArg1, TComponent>(Func<IHostEnvironment, TArg1, TComponent> factory)
public TComponent CreateComponent(IHostEnvironment env, TArg1 argument1)
{
return new SimpleComponentFactory<TArg1, TComponent>(factory);
return _factory(env, argument1);
}
}
/// <summary>
/// A class for creating a component when we take one extra parameter
/// (and an <see cref="IHostEnvironment"/>) that simply wraps a delegate which
/// creates the component.
/// </summary>
private sealed class SimpleComponentFactory<TArg1, TArg2, TComponent> : IComponentFactory<TArg1, TArg2, TComponent>
{
private readonly Func<IHostEnvironment, TArg1, TArg2, TComponent> _factory;
public SimpleComponentFactory(Func<IHostEnvironment, TArg1, TArg2, TComponent> factory)
{
_factory = factory;
}
/// <summary>
/// Creates a component factory when we take two extra parameters (and an
/// <see cref="IHostEnvironment"/>) that simply wraps a delegate which creates the component.
/// </summary>
public static IComponentFactory<TArg1, TArg2, TComponent> CreateFromFunction<TArg1, TArg2, TComponent>(Func<IHostEnvironment, TArg1, TArg2, TComponent> factory)
public TComponent CreateComponent(IHostEnvironment env, TArg1 argument1, TArg2 argument2)
{
return new SimpleComponentFactory<TArg1, TArg2, TComponent>(factory);
return _factory(env, argument1, argument2);
}
}
/// <summary>
/// A class for creating a component when we take three extra parameters
/// (and an <see cref="IHostEnvironment"/>) that simply wraps a delegate which
/// creates the component.
/// </summary>
private sealed class SimpleComponentFactory<TArg1, TArg2, TArg3, TComponent> : IComponentFactory<TArg1, TArg2, TArg3, TComponent>
{
private readonly Func<IHostEnvironment, TArg1, TArg2, TArg3, TComponent> _factory;
public SimpleComponentFactory(Func<IHostEnvironment, TArg1, TArg2, TArg3, TComponent> factory)
{
_factory = factory;
}
/// <summary>
/// Creates a component factory when we take three extra parameters (and an
/// <see cref="IHostEnvironment"/>) that simply wraps a delegate which creates the component.
/// </summary>
public static IComponentFactory<TArg1, TArg2, TArg3, TComponent> CreateFromFunction<TArg1, TArg2, TArg3, TComponent>(Func<IHostEnvironment, TArg1, TArg2, TArg3, TComponent> factory)
public TComponent CreateComponent(IHostEnvironment env, TArg1 argument1, TArg2 argument2, TArg3 argument3)
{
return new SimpleComponentFactory<TArg1, TArg2, TArg3, TComponent>(factory);
}
/// <summary>
/// A class for creating a component with no extra parameters (other than an <see cref="IHostEnvironment"/>)
/// that simply wraps a delegate which creates the component.
/// </summary>
private sealed class SimpleComponentFactory<TComponent> : IComponentFactory<TComponent>
{
private readonly Func<IHostEnvironment, TComponent> _factory;
public SimpleComponentFactory(Func<IHostEnvironment, TComponent> factory)
{
_factory = factory;
}
public TComponent CreateComponent(IHostEnvironment env)
{
return _factory(env);
}
}
/// <summary>
/// A class for creating a component when we take one extra parameter
/// (and an <see cref="IHostEnvironment"/>) that simply wraps a delegate which
/// creates the component.
/// </summary>
private sealed class SimpleComponentFactory<TArg1, TComponent> : IComponentFactory<TArg1, TComponent>
{
private readonly Func<IHostEnvironment, TArg1, TComponent> _factory;
public SimpleComponentFactory(Func<IHostEnvironment, TArg1, TComponent> factory)
{
_factory = factory;
}
public TComponent CreateComponent(IHostEnvironment env, TArg1 argument1)
{
return _factory(env, argument1);
}
}
/// <summary>
/// A class for creating a component when we take one extra parameter
/// (and an <see cref="IHostEnvironment"/>) that simply wraps a delegate which
/// creates the component.
/// </summary>
private sealed class SimpleComponentFactory<TArg1, TArg2, TComponent> : IComponentFactory<TArg1, TArg2, TComponent>
{
private readonly Func<IHostEnvironment, TArg1, TArg2, TComponent> _factory;
public SimpleComponentFactory(Func<IHostEnvironment, TArg1, TArg2, TComponent> factory)
{
_factory = factory;
}
public TComponent CreateComponent(IHostEnvironment env, TArg1 argument1, TArg2 argument2)
{
return _factory(env, argument1, argument2);
}
}
/// <summary>
/// A class for creating a component when we take three extra parameters
/// (and an <see cref="IHostEnvironment"/>) that simply wraps a delegate which
/// creates the component.
/// </summary>
private sealed class SimpleComponentFactory<TArg1, TArg2, TArg3, TComponent> : IComponentFactory<TArg1, TArg2, TArg3, TComponent>
{
private readonly Func<IHostEnvironment, TArg1, TArg2, TArg3, TComponent> _factory;
public SimpleComponentFactory(Func<IHostEnvironment, TArg1, TArg2, TArg3, TComponent> factory)
{
_factory = factory;
}
public TComponent CreateComponent(IHostEnvironment env, TArg1 argument1, TArg2 argument2, TArg3 argument3)
{
return _factory(env, argument1, argument2, argument3);
}
return _factory(env, argument1, argument2, argument3);
}
}
}

Просмотреть файл

@ -4,20 +4,19 @@
using System;
namespace Microsoft.ML
{
/// <summary>
/// The base attribute type for all attributes used for extensibility purposes.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public abstract class ExtensionBaseAttribute : Attribute
{
public string ContractName { get; }
namespace Microsoft.ML;
[BestFriend]
private protected ExtensionBaseAttribute(string contractName)
{
ContractName = contractName;
}
/// <summary>
/// The base attribute type for all attributes used for extensibility purposes.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public abstract class ExtensionBaseAttribute : Attribute
{
public string ContractName { get; }
[BestFriend]
private protected ExtensionBaseAttribute(string contractName)
{
ContractName = contractName;
}
}

Просмотреть файл

@ -8,229 +8,228 @@ using System.Reflection;
using Microsoft.ML.Internal.Utilities;
using Microsoft.ML.Runtime;
namespace Microsoft.ML
namespace Microsoft.ML;
/// <summary>
/// Common signature type with no extra parameters.
/// </summary>
[BestFriend]
internal delegate void SignatureDefault();
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
[BestFriend]
internal sealed class LoadableClassAttribute : LoadableClassAttributeBase
{
/// <summary>
/// Common signature type with no extra parameters.
/// Assembly attribute used to specify that a class is loadable by a machine learning
/// host environment, such as TLC
/// </summary>
[BestFriend]
internal delegate void SignatureDefault();
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
[BestFriend]
internal sealed class LoadableClassAttribute : LoadableClassAttributeBase
/// <param name="instType">The class type that is loadable</param>
/// <param name="argType">The argument type that the constructor takes (may be null)</param>
/// <param name="sigType">The signature of the constructor of this class (in addition to the arguments parameter)</param>
/// <param name="userName">The name to use when presenting a list to users</param>
/// <param name="loadNames">The names that can be used to load the class, for example, from a command line</param>
public LoadableClassAttribute(Type instType, Type argType, Type sigType, string userName, params string[] loadNames)
: base(null, instType, instType, argType, new[] { sigType }, userName, loadNames)
{
/// <summary>
/// Assembly attribute used to specify that a class is loadable by a machine learning
/// host environment, such as TLC
/// </summary>
/// <param name="instType">The class type that is loadable</param>
/// <param name="argType">The argument type that the constructor takes (may be null)</param>
/// <param name="sigType">The signature of the constructor of this class (in addition to the arguments parameter)</param>
/// <param name="userName">The name to use when presenting a list to users</param>
/// <param name="loadNames">The names that can be used to load the class, for example, from a command line</param>
public LoadableClassAttribute(Type instType, Type argType, Type sigType, string userName, params string[] loadNames)
: base(null, instType, instType, argType, new[] { sigType }, userName, loadNames)
{
}
/// <summary>
/// Assembly attribute used to specify that a class is loadable by a machine learning
/// host environment, such as TLC
/// </summary>
/// <param name="instType">The class type that is loadable</param>
/// <param name="loaderType">The class type that contains the construction method</param>
/// <param name="argType">The argument type that the constructor takes (may be null)</param>
/// <param name="sigType">The signature of the constructor of this class (in addition to the arguments parameter)</param>
/// <param name="userName">The name to use when presenting a list to users</param>
/// <param name="loadNames">The names that can be used to load the class, for example, from a command line</param>
public LoadableClassAttribute(Type instType, Type loaderType, Type argType, Type sigType, string userName, params string[] loadNames)
: base(null, instType, loaderType, argType, new[] { sigType }, userName, loadNames)
{
}
public LoadableClassAttribute(Type instType, Type argType, Type[] sigTypes, string userName, params string[] loadNames)
: base(null, instType, instType, argType, sigTypes, userName, loadNames)
{
}
public LoadableClassAttribute(Type instType, Type loaderType, Type argType, Type[] sigTypes, string userName, params string[] loadNames)
: base(null, instType, loaderType, argType, sigTypes, userName, loadNames)
{
}
/// <summary>
/// Assembly attribute used to specify that a class is loadable by a machine learning
/// host environment, such as TLC
/// </summary>
/// <param name="summary">The description summary of the class type</param>
/// <param name="instType">The class type that is loadable</param>
/// <param name="argType">The argument type that the constructor takes (may be null)</param>
/// <param name="sigType">The signature of the constructor of this class (in addition to the arguments parameter)</param>
/// <param name="userName">The name to use when presenting a list to users</param>
/// <param name="loadNames">The names that can be used to load the class, for example, from a command line</param>
public LoadableClassAttribute(string summary, Type instType, Type argType, Type sigType, string userName, params string[] loadNames)
: base(summary, instType, instType, argType, new[] { sigType }, userName, loadNames)
{
}
/// <summary>
/// Assembly attribute used to specify that a class is loadable by a machine learning
/// host environment, such as TLC
/// </summary>
/// <param name="summary">The description summary of the class type</param>
/// <param name="instType">The class type that is loadable</param>
/// <param name="loaderType">The class type that contains the construction method</param>
/// <param name="argType">The argument type that the constructor takes (may be null)</param>
/// <param name="sigType">The signature of the constructor of this class (in addition to the arguments parameter)</param>
/// <param name="userName">The name to use when presenting a list to users</param>
/// <param name="loadNames">The names that can be used to load the class, for example, from a command line</param>
public LoadableClassAttribute(string summary, Type instType, Type loaderType, Type argType, Type sigType, string userName, params string[] loadNames)
: base(summary, instType, loaderType, argType, new[] { sigType }, userName, loadNames)
{
}
public LoadableClassAttribute(string summary, Type instType, Type argType, Type[] sigTypes, string userName, params string[] loadNames)
: base(summary, instType, instType, argType, sigTypes, userName, loadNames)
{
}
public LoadableClassAttribute(string summary, Type instType, Type loaderType, Type argType, Type[] sigTypes, string userName, params string[] loadNames)
: base(summary, instType, loaderType, argType, sigTypes, userName, loadNames)
{
}
}
internal abstract class LoadableClassAttributeBase : Attribute
/// <summary>
/// Assembly attribute used to specify that a class is loadable by a machine learning
/// host environment, such as TLC
/// </summary>
/// <param name="instType">The class type that is loadable</param>
/// <param name="loaderType">The class type that contains the construction method</param>
/// <param name="argType">The argument type that the constructor takes (may be null)</param>
/// <param name="sigType">The signature of the constructor of this class (in addition to the arguments parameter)</param>
/// <param name="userName">The name to use when presenting a list to users</param>
/// <param name="loadNames">The names that can be used to load the class, for example, from a command line</param>
public LoadableClassAttribute(Type instType, Type loaderType, Type argType, Type sigType, string userName, params string[] loadNames)
: base(null, instType, loaderType, argType, new[] { sigType }, userName, loadNames)
{
// Note: these properties have private setters to make attribute parsing easier - the values
// are all guaranteed to be in the ConstructorArguments of the CustomAttributeData
// (no named arguments).
}
/// <summary>
/// The type that is created/loaded.
/// </summary>
public Type InstanceType { get; private set; }
public LoadableClassAttribute(Type instType, Type argType, Type[] sigTypes, string userName, params string[] loadNames)
: base(null, instType, instType, argType, sigTypes, userName, loadNames)
{
}
/// <summary>
/// The type that contains the construction method, whether static Instance property,
/// static Create method, or constructor. Of course, a constructor is only permissible if
/// this type derives from InstanceType. This defaults to the same as InstanceType.
/// </summary>
public Type LoaderType { get; private set; }
public LoadableClassAttribute(Type instType, Type loaderType, Type argType, Type[] sigTypes, string userName, params string[] loadNames)
: base(null, instType, loaderType, argType, sigTypes, userName, loadNames)
{
}
/// <summary>
/// The command line arguments object type. This should be null if there isn't one.
/// </summary>
public Type ArgType { get; private set; }
/// <summary>
/// Assembly attribute used to specify that a class is loadable by a machine learning
/// host environment, such as TLC
/// </summary>
/// <param name="summary">The description summary of the class type</param>
/// <param name="instType">The class type that is loadable</param>
/// <param name="argType">The argument type that the constructor takes (may be null)</param>
/// <param name="sigType">The signature of the constructor of this class (in addition to the arguments parameter)</param>
/// <param name="userName">The name to use when presenting a list to users</param>
/// <param name="loadNames">The names that can be used to load the class, for example, from a command line</param>
public LoadableClassAttribute(string summary, Type instType, Type argType, Type sigType, string userName, params string[] loadNames)
: base(summary, instType, instType, argType, new[] { sigType }, userName, loadNames)
{
}
/// <summary>
/// This indicates the extra parameter types. It must be a delegate type. The return type should be void.
/// The parameter types of the SigType delegate should NOT include the ArgType.
/// </summary>
public Type[] SigTypes { get; private set; }
/// <summary>
/// Assembly attribute used to specify that a class is loadable by a machine learning
/// host environment, such as TLC
/// </summary>
/// <param name="summary">The description summary of the class type</param>
/// <param name="instType">The class type that is loadable</param>
/// <param name="loaderType">The class type that contains the construction method</param>
/// <param name="argType">The argument type that the constructor takes (may be null)</param>
/// <param name="sigType">The signature of the constructor of this class (in addition to the arguments parameter)</param>
/// <param name="userName">The name to use when presenting a list to users</param>
/// <param name="loadNames">The names that can be used to load the class, for example, from a command line</param>
public LoadableClassAttribute(string summary, Type instType, Type loaderType, Type argType, Type sigType, string userName, params string[] loadNames)
: base(summary, instType, loaderType, argType, new[] { sigType }, userName, loadNames)
{
}
/// <summary>
/// Note that CtorTypes includes the ArgType (if there is one), and the parameter types of the SigType.
/// </summary>
public Type[] CtorTypes { get; private set; }
public LoadableClassAttribute(string summary, Type instType, Type argType, Type[] sigTypes, string userName, params string[] loadNames)
: base(summary, instType, instType, argType, sigTypes, userName, loadNames)
{
}
/// <summary>
/// The description summary of the class type.
/// </summary>
public string Summary { get; private set; }
public LoadableClassAttribute(string summary, Type instType, Type loaderType, Type argType, Type[] sigTypes, string userName, params string[] loadNames)
: base(summary, instType, loaderType, argType, sigTypes, userName, loadNames)
{
}
}
/// <summary>
/// UserName may be null or empty indicating that it should be hidden in UI.
/// </summary>
public string UserName { get; private set; }
public string[] LoadNames { get; private set; }
internal abstract class LoadableClassAttributeBase : Attribute
{
// Note: these properties have private setters to make attribute parsing easier - the values
// are all guaranteed to be in the ConstructorArguments of the CustomAttributeData
// (no named arguments).
// REVIEW: This is out of step with the remainder of the class. However, my opinion is that the
// LoadableClassAttribute class's design is worth reconsideration: having so many Type and string arguments
// be defined *without names* in a constructor has led to enormous confusion.
/// <summary>
/// The type that is created/loaded.
/// </summary>
public Type InstanceType { get; private set; }
// REVIEW: Presumably it would be beneficial to have multiple documents.
/// <summary>
/// The type that contains the construction method, whether static Instance property,
/// static Create method, or constructor. Of course, a constructor is only permissible if
/// this type derives from InstanceType. This defaults to the same as InstanceType.
/// </summary>
public Type LoaderType { get; private set; }
/// <summary>
/// This should indicate a path within the <code>doc/public</code> directory next to the TLC
/// solution, where the documentation lies. This value will be used as part of a URL, so,
/// the path separator should be phrased as '/' forward slashes rather than backslashes.</summary>
public string DocName { get; set; }
/// <summary>
/// The command line arguments object type. This should be null if there isn't one.
/// </summary>
public Type ArgType { get; private set; }
protected LoadableClassAttributeBase(string summary, Type instType, Type loaderType, Type argType, Type[] sigTypes, string userName, params string[] loadNames)
/// <summary>
/// This indicates the extra parameter types. It must be a delegate type. The return type should be void.
/// The parameter types of the SigType delegate should NOT include the ArgType.
/// </summary>
public Type[] SigTypes { get; private set; }
/// <summary>
/// Note that CtorTypes includes the ArgType (if there is one), and the parameter types of the SigType.
/// </summary>
public Type[] CtorTypes { get; private set; }
/// <summary>
/// The description summary of the class type.
/// </summary>
public string Summary { get; private set; }
/// <summary>
/// UserName may be null or empty indicating that it should be hidden in UI.
/// </summary>
public string UserName { get; private set; }
public string[] LoadNames { get; private set; }
// REVIEW: This is out of step with the remainder of the class. However, my opinion is that the
// LoadableClassAttribute class's design is worth reconsideration: having so many Type and string arguments
// be defined *without names* in a constructor has led to enormous confusion.
// REVIEW: Presumably it would be beneficial to have multiple documents.
/// <summary>
/// This should indicate a path within the <code>doc/public</code> directory next to the TLC
/// solution, where the documentation lies. This value will be used as part of a URL, so,
/// the path separator should be phrased as '/' forward slashes rather than backslashes.</summary>
public string DocName { get; set; }
protected LoadableClassAttributeBase(string summary, Type instType, Type loaderType, Type argType, Type[] sigTypes, string userName, params string[] loadNames)
{
Contracts.CheckValueOrNull(summary);
Contracts.CheckValue(instType, nameof(instType));
Contracts.CheckValue(loaderType, nameof(loaderType));
Contracts.CheckNonEmpty(sigTypes, nameof(sigTypes));
if (Utils.Size(loadNames) == 0)
loadNames = new string[] { userName };
if (loadNames.Any(s => string.IsNullOrWhiteSpace(s)))
throw Contracts.ExceptEmpty(nameof(loadNames), "LoadableClass loadName parameter can't be empty");
var sigType = sigTypes[0];
Contracts.CheckValue(sigType, nameof(sigTypes));
Type[] types;
Contracts.CheckParam(sigType.BaseType == typeof(System.MulticastDelegate), nameof(sigTypes), "LoadableClass signature type must be a delegate type");
var meth = sigType.GetMethod("Invoke");
Contracts.CheckParam(meth != null, nameof(sigTypes), "LoadableClass signature type must be a delegate type");
Contracts.CheckParam(meth.ReturnType == typeof(void), nameof(sigTypes), "LoadableClass signature type must be a delegate type with void return");
var parms = meth.GetParameters();
int itypeBase = 0;
if (argType != null)
{
Contracts.CheckValueOrNull(summary);
Contracts.CheckValue(instType, nameof(instType));
Contracts.CheckValue(loaderType, nameof(loaderType));
Contracts.CheckNonEmpty(sigTypes, nameof(sigTypes));
types = new Type[1 + parms.Length];
types[itypeBase++] = argType;
}
else if (parms.Length > 0)
types = new Type[parms.Length];
else
types = Type.EmptyTypes;
if (Utils.Size(loadNames) == 0)
loadNames = new string[] { userName };
for (int itype = 0; itype < parms.Length; itype++)
{
var parm = parms[itype];
if ((parm.Attributes & (ParameterAttributes.Out | ParameterAttributes.Retval)) != 0)
throw Contracts.Except("Invalid signature parameter attributes");
types[itypeBase + itype] = parm.ParameterType;
}
if (loadNames.Any(s => string.IsNullOrWhiteSpace(s)))
throw Contracts.ExceptEmpty(nameof(loadNames), "LoadableClass loadName parameter can't be empty");
var sigType = sigTypes[0];
for (int i = 1; i < sigTypes.Length; i++)
{
sigType = sigTypes[i];
Contracts.CheckValue(sigType, nameof(sigTypes));
Type[] types;
Contracts.CheckParam(sigType.BaseType == typeof(System.MulticastDelegate), nameof(sigTypes), "LoadableClass signature type must be a delegate type");
var meth = sigType.GetMethod("Invoke");
Contracts.Check(sigType.BaseType == typeof(System.MulticastDelegate), "LoadableClass signature type must be a delegate type");
meth = sigType.GetMethod("Invoke");
Contracts.CheckParam(meth != null, nameof(sigTypes), "LoadableClass signature type must be a delegate type");
Contracts.CheckParam(meth.ReturnType == typeof(void), nameof(sigTypes), "LoadableClass signature type must be a delegate type with void return");
var parms = meth.GetParameters();
int itypeBase = 0;
if (argType != null)
{
types = new Type[1 + parms.Length];
types[itypeBase++] = argType;
}
else if (parms.Length > 0)
types = new Type[parms.Length];
else
types = Type.EmptyTypes;
parms = meth.GetParameters();
Contracts.CheckParam(parms.Length + itypeBase == types.Length, nameof(sigTypes), "LoadableClass signatures must have the same number of parameters");
for (int itype = 0; itype < parms.Length; itype++)
{
var parm = parms[itype];
if ((parm.Attributes & (ParameterAttributes.Out | ParameterAttributes.Retval)) != 0)
throw Contracts.Except("Invalid signature parameter attributes");
types[itypeBase + itype] = parm.ParameterType;
throw Contracts.ExceptParam(nameof(sigTypes), "Invalid signature parameter attributes");
Contracts.CheckParam(types[itypeBase + itype] == parm.ParameterType, nameof(sigTypes),
"LoadableClass signatures must have the same set of parameters");
}
for (int i = 1; i < sigTypes.Length; i++)
{
sigType = sigTypes[i];
Contracts.CheckValue(sigType, nameof(sigTypes));
Contracts.Check(sigType.BaseType == typeof(System.MulticastDelegate), "LoadableClass signature type must be a delegate type");
meth = sigType.GetMethod("Invoke");
Contracts.CheckParam(meth != null, nameof(sigTypes), "LoadableClass signature type must be a delegate type");
Contracts.CheckParam(meth.ReturnType == typeof(void), nameof(sigTypes), "LoadableClass signature type must be a delegate type with void return");
parms = meth.GetParameters();
Contracts.CheckParam(parms.Length + itypeBase == types.Length, nameof(sigTypes), "LoadableClass signatures must have the same number of parameters");
for (int itype = 0; itype < parms.Length; itype++)
{
var parm = parms[itype];
if ((parm.Attributes & (ParameterAttributes.Out | ParameterAttributes.Retval)) != 0)
throw Contracts.ExceptParam(nameof(sigTypes), "Invalid signature parameter attributes");
Contracts.CheckParam(types[itypeBase + itype] == parm.ParameterType, nameof(sigTypes),
"LoadableClass signatures must have the same set of parameters");
}
}
InstanceType = instType;
LoaderType = loaderType;
ArgType = argType;
SigTypes = sigTypes;
CtorTypes = types;
Summary = summary;
UserName = userName;
LoadNames = loadNames;
}
InstanceType = instType;
LoaderType = loaderType;
ArgType = argType;
SigTypes = sigTypes;
CtorTypes = types;
Summary = summary;
UserName = userName;
LoadNames = loadNames;
}
}