Assembly.Get does not work in single file executable deployments
Hi,
We are using MTConnect.NET 6.5.0. We deploy our application as a single file executable. Given this context Assmbly.Get() method found in MTConnect.NET uses Assebly.Location to find all dll files. But, in single file dployments Assembly.Location returns empty and actually all dll files are compressed and embedded inside the single file executable.
Current workaround for us was to create a static class and add document formatters to ResponseDocumentFormatter private static fields using reflection.
public static class MtConnectRuntime
{
public static void Initialize()
{
SetMtConnectResponseDocumentFormatters();
}
private static void SetMtConnectResponseDocumentFormatters()
{
// [AÖ] This is needed beacuse when deployment is selected SingleFile Assemblies.Get() (found in MTConnect.NET lib) can not inspect assemblies
// See: https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/warnings/il3000
// See: https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview?tabs=cli
try
{
var fields = typeof(ResponseDocumentFormatter).GetFields(BindingFlags.NonPublic | BindingFlags.Static);
var _firstRead = fields.FirstOrDefault(x => x.Name == "_firstRead");
var _formatters = fields.FirstOrDefault(x => x.Name == "_formatters");
if (_firstRead != null)
{
_firstRead.SetValue(null, false);
}
if (_formatters != null)
{
var formatters = (ConcurrentDictionary<string, IResponseDocumentFormatter>)_formatters.GetValue(null);
formatters.Clear();
var xml = new XmlResponseDocumentFormatter();
formatters.TryAdd(xml.Id.ToLower(), xml);
var json = new JsonResponseDocumentFormatter();
formatters.TryAdd(json.Id.ToLower(), json);
var html = new JsonHttpResponseDocumentFormatter();
formatters.TryAdd(html.Id.ToLower(), html);
var mqtt = new JsonMqttResponseDocumentFormatter();
formatters.TryAdd(mqtt.Id.ToLower(), mqtt);
}
}
catch(Exception ex)
{
Console.WriteLine($"{nameof(MtConnectRuntime.SetMtConnectResponseDocumentFormatters)} {ex.ToErrorMessage()}\r\n{ex.StackTrace}");
}
}
}
Thanks for the information! Glad to hear you have a workaround and I'll see if there is a good way to toggle how the formatters are loaded.
It looks like using the below arguments with the DotNet CLI publish command seems to work:
dotnet publish -c:Release -f:net8.0 -r:win-x64 -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true --self-contained false
The IncludeAllContentForSelfExtract option seems to be what allows the combined assemblies to be read as if they were separate.
Thanks for bringing this up! I'm planning to build future versions using this.