diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateXmlSerializers.cs b/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateXmlSerializers.cs
new file mode 100644
index 00000000000000..c66acf6e07764e
--- /dev/null
+++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateXmlSerializers.cs
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.XmlSerializer.Generator
+{
+ ///
+ /// MSBuild task to run the Microsoft.XmlSerializer.Generator directly,
+ /// without spawning a new process.
+ ///
+ public class GenerateXmlSerializers : Task
+ {
+ ///
+ /// Path to the target assembly (usually the output DLL).
+ ///
+ [Required]
+ public string AssemblyPath { get; set; }
+
+ ///
+ /// Optional path to a response file containing additional generator arguments.
+ ///
+ public string RspFilePath { get; set; }
+
+ ///
+ /// Force regeneration of serializers even if they exist.
+ ///
+ public bool Force { get; set; }
+
+ ///
+ /// Run in quiet mode with minimal output.
+ ///
+ public bool Quiet { get; set; }
+
+ ///
+ /// If true, errors during serializer generation will be suppressed.
+ ///
+ public bool IgnoreErrors { get; set; }
+
+ ///
+ /// Executes the XmlSerializer generator.
+ ///
+ public override bool Execute()
+ {
+ var args = new List();
+
+ if (!string.IsNullOrEmpty(AssemblyPath))
+ args.Add(AssemblyPath);
+
+ if (Force)
+ args.Add("--force");
+
+ if (Quiet)
+ args.Add("--quiet");
+
+ if (!string.IsNullOrEmpty(RspFilePath))
+ args.Add(RspFilePath);
+
+ Sgen sgen = new Sgen();
+ Sgen.InfoWriter = new InfoTextWriter(Log);
+ Sgen.WarningWriter = new WarningTextWriter(Log);
+ Sgen.ErrorWriter = new ErrorTextWriter(Log);
+
+ int exitCode = sgen.Run(args.ToArray());
+
+ if (exitCode != 0)
+ {
+ Log.LogError("XmlSerializer failed with exit code {0}.", exitCode);
+ }
+
+ return IgnoreErrors || exitCode == 0;
+ }
+ }
+}
diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/LogWriter.cs b/src/libraries/Microsoft.XmlSerializer.Generator/src/LogWriter.cs
new file mode 100644
index 00000000000000..89f1bb12c3bdb5
--- /dev/null
+++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/LogWriter.cs
@@ -0,0 +1,95 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Text;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace Microsoft.XmlSerializer.Generator
+{
+ internal sealed class InfoTextWriter : TextWriter
+ {
+ private readonly TaskLoggingHelper _log;
+
+ public InfoTextWriter(TaskLoggingHelper log)
+ {
+ _log = log ?? throw new ArgumentNullException(nameof(log));
+ }
+
+ public override Encoding Encoding => Encoding.UTF8;
+
+ public override void Write(string? value)
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ _log.LogMessage(MessageImportance.High, value);
+ }
+ }
+
+ public override void WriteLine(string? value)
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ _log.LogMessage(MessageImportance.High, value);
+ }
+ }
+ }
+
+ internal sealed class WarningTextWriter : TextWriter
+ {
+ private readonly TaskLoggingHelper _log;
+
+ public WarningTextWriter(TaskLoggingHelper log)
+ {
+ _log = log ?? throw new ArgumentNullException(nameof(log));
+ }
+
+ public override Encoding Encoding => Encoding.UTF8;
+
+ public override void Write(string? value)
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ _log.LogWarning(value);
+ }
+ }
+
+ public override void WriteLine(string? value)
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ _log.LogWarning(value);
+ }
+ }
+ }
+
+ internal sealed class ErrorTextWriter : TextWriter
+ {
+ private readonly TaskLoggingHelper _log;
+
+ public ErrorTextWriter(TaskLoggingHelper log)
+ {
+ _log = log ?? throw new ArgumentNullException(nameof(log));
+ }
+
+ public override Encoding Encoding => Encoding.UTF8;
+
+ public override void Write(string? value)
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ _log.LogError(value);
+ }
+ }
+
+ public override void WriteLine(string? value)
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ _log.LogError(value);
+ }
+ }
+ }
+}
diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj b/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj
index a05c036040c043..4990a110cdf788 100644
--- a/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj
+++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj
@@ -1,4 +1,4 @@
-
+
netstandard2.0
@@ -22,22 +22,24 @@
+
+
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs
index 74f2d111df056d..0daee0c81607af 100644
--- a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs
+++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs
@@ -25,8 +25,11 @@ public static int Main(string[] args)
private static string s_references = string.Empty;
private static readonly Dictionary s_referencedic = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ public static TextWriter InfoWriter { get; internal set; } = Console.Out;
+ public static TextWriter WarningWriter { get; internal set; } = Console.Out;
+ public static TextWriter ErrorWriter { get; internal set; } = Console.Error;
- private int Run(string[] args)
+ internal int Run(string[] args)
{
string assembly = null;
var types = new List();
@@ -177,7 +180,7 @@ private int Run(string[] args)
{
foreach (string err in errs)
{
- Console.Error.WriteLine(FormatMessage(parsableErrors, true, SR.Format(SR.Warning, err)));
+ ErrorWriter.WriteLine(FormatMessage(parsableErrors, true, SR.Format(SR.Warning, err)));
}
}
@@ -185,7 +188,7 @@ private int Run(string[] args)
{
if (assembly == null)
{
- Console.Error.WriteLine(FormatMessage(parsableErrors, false, SR.Format(SR.ErrMissingRequiredArgument, SR.Format(SR.ErrAssembly, "assembly"))));
+ ErrorWriter.WriteLine(FormatMessage(parsableErrors, false, SR.Format(SR.ErrMissingRequiredArgument, SR.Format(SR.ErrAssembly, "assembly"))));
}
WriteHelp();
@@ -194,8 +197,8 @@ private int Run(string[] args)
if (disableRun)
{
- Console.WriteLine("This tool is not intended to be used directly.");
- Console.WriteLine("Please refer to https://go.microsoft.com/fwlink/?linkid=858594 on how to use it.");
+ InfoWriter.WriteLine("This tool is not intended to be used directly.");
+ InfoWriter.WriteLine("Please refer to https://go.microsoft.com/fwlink/?linkid=858594 on how to use it.");
return 0;
}
@@ -254,7 +257,7 @@ private static void GenerateFile(List typeNames, string defaultNamespace
Type type = assembly.GetType(typeName);
if (type == null)
{
- Console.Error.WriteLine(FormatMessage(parsableerrors, false, SR.Format(SR.ErrorDetails, SR.Format(SR.ErrLoadType, typeName, assemblyName))));
+ ErrorWriter.WriteLine(FormatMessage(parsableerrors, false, SR.Format(SR.ErrorDetails, SR.Format(SR.ErrLoadType, typeName, assemblyName))));
}
types[typeIndex++] = type;
@@ -275,7 +278,7 @@ private static void GenerateFile(List typeNames, string defaultNamespace
{
if (verbose)
{
- Console.WriteLine(SR.Format(SR.ImportInfo, type.Name, i + 1, types.Length));
+ InfoWriter.WriteLine(SR.Format(SR.ImportInfo, type.Name, i + 1, types.Length));
}
bool isObsolete = false;
@@ -300,7 +303,7 @@ private static void GenerateFile(List typeNames, string defaultNamespace
{
if (verbose)
{
- Console.Out.WriteLine(FormatMessage(parsableerrors, true, SR.Format(SR.InfoIgnoreType, type.FullName)));
+ InfoWriter.WriteLine(FormatMessage(parsableerrors, true, SR.Format(SR.InfoIgnoreType, type.FullName)));
WriteWarning(e, parsableerrors);
}
@@ -372,7 +375,7 @@ private static void GenerateFile(List typeNames, string defaultNamespace
if (method == null)
{
- Console.Error.WriteLine(FormatMessage(parsableerrors: false, warning: false, message: SR.GenerateSerializerNotFound));
+ ErrorWriter.WriteLine(FormatMessage(parsableerrors: false, warning: false, message: SR.GenerateSerializerNotFound));
}
else
{
@@ -404,22 +407,21 @@ private static void GenerateFile(List typeNames, string defaultNamespace
{
if (!silent)
{
- Console.Out.WriteLine(SR.Format(SR.InfoFileName, codePath));
- Console.Out.WriteLine(SR.Format(SR.InfoGeneratedFile, assembly.Location, codePath));
+ InfoWriter.WriteLine(SR.Format(SR.InfoFileName, codePath));
+ InfoWriter.WriteLine(SR.Format(SR.InfoGeneratedFile, assembly.Location, codePath));
}
}
else
{
- Console.Out.WriteLine(FormatMessage(parsableerrors, false, SR.Format(SR.ErrGenerationFailed, assembly.Location)));
+ InfoWriter.WriteLine(FormatMessage(parsableerrors, false, SR.Format(SR.ErrGenerationFailed, assembly.Location)));
}
}
else
{
- Console.Out.WriteLine(FormatMessage(parsableerrors, true, SR.Format(SR.InfoNoSerializableTypes, assembly.Location)));
+ InfoWriter.WriteLine(FormatMessage(parsableerrors, true, SR.Format(SR.InfoNoSerializableTypes, assembly.Location)));
}
}
-
private static bool ArgumentMatch(string arg, string formal)
{
// Full name format, eg: --assembly
@@ -459,7 +461,7 @@ private static void ImportType(Type type, string defaultNamespace, List
-
+
+