I have a function that has an input of type object. The value that comes to this function is an array of a class called 'Box' I've made the following tries but not able to convert the object value to Box[].
internal class BoxConverter : IRunDataConverter
{
string IRunDataConverter.Key => "boxes";
object IRunDataConverter.ConvertToPublishable(object value)
{
//return value;
object[] arr = (object[])value;//value is an array of Box
System.Diagnostics.Debug.WriteLine(arr[0].GetType());// --> WF.CV.Entity.Box
System.Diagnostics.Debug.WriteLine(typeof(Box));// --> WF.CV.Entity.Box
System.Diagnostics.Debug.WriteLine(arr[0].GetType().AssemblyQualifiedName);// --> WF.CV.Entity.Box, WF.CV, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
System.Diagnostics.Debug.WriteLine(typeof(Box).AssemblyQualifiedName);// --> WF.CV.Entity.Box, WF.CV, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
bool sameTypes = typeof(Box) == arr[0].GetType();// FALSE
Box[] try1 = arr.OfType<Box>().ToArray();// try1 -> array with zero lenght.
Box[] boxes = new Box[arr.Length];
for(int i=0; i<arr.Length; i++)
{
Box box = (Box)arr[i]; // Error:
// System.InvalidCastException:
// '[A]WF.CV.Entity.Box cannot be cast to
// [B]WF.CV.Entity.Box. Type A originates from 'WF.CV, Version=1.0.0.0,
// Culture=neutral, PublicKeyToken=null' in the context 'Default' at
// location 'C:\_koray\korhun\WF\WF.Web\bin\Debug\net5.0\WF.CV.dll'.
// Type B originates from 'WF.CV, Version=1.0.0.0,
// Culture=neutral, PublicKeyToken=null' in the context 'Default' in a byte array.'
dynamic val = new System.Dynamic.ExpandoObject();
val.Name = box.Name;
val.Confidence = box.Confidence;
val.Coords = box.Coords;
boxes[i] = val;
}
return boxes;
}
}
When I type typeof(Box) and arr[0].GetType() into Immediate Window I get the following result. (Unseen parts in the picture are same.)

This is the Box class:
using Newtonsoft.Json;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WF.CV.Entity
{
[DebuggerDisplay("Name: {Name} Confidence: {Confidence} Location: {Location}")]
public class Box
{
public string Name { get; set; }
public float Confidence { get; set; }
/// <summary>
/// Normalized MinX, MinY, MaxX, MaxY
/// </summary>
public float[] Coords { get; set; }
[JsonIgnore]
public float Left => Coords[0];
[JsonIgnore]
public float Right => Coords[2];
[JsonIgnore]
public float Top => Coords[1];
[JsonIgnore]
public float Bottom => Coords[3];
[JsonIgnore]
public float Width => Coords[2] - Coords[0];
[JsonIgnore]
public float Height => Coords[3] - Coords[1];
public Rect GetRect(int width, int height)
{
int x = (int)(Coords[0] * width);
int y = (int)(Coords[1] * height);
int w = (int)((Coords[2] - Coords[0]) * width);
int h = (int)((Coords[3] - Coords[1]) * height);
return new Rect(x, y, w, h);
}
}
}
This happens inside an unsafe dll being used by an Entity Framework and Web API projects, in Visual Studio 2019, Windows 10 environment. All projects' target framework is .NET 5.0.
Update - What happens before:
IRunDataConverter is being called with this manager class. It's in a non-unsafe dll:
public class RunDataConverterManager : IRunDataConverterManager
{
private readonly ILogger<IRunDataConverter> logger;
private readonly IServiceProvider provider;
public RunDataConverterManager(ILogger<IRunDataConverter> logger, IServiceProvider provider)
{
this.logger = logger;
this.provider = provider;
initialize();
}
private Dictionary<string, IRunDataConverter> converters;
private void initialize()
{
this.converters = new Dictionary<string, IRunDataConverter>();
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
foreach (string dll in Directory.GetFiles(path, "*.dll"))
AppDomain.CurrentDomain.Load(File.ReadAllBytes(dll));
var type = typeof(IRunDataConverter);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p) && p.IsClass);
HashSet<string> hs = new();
foreach (Type ty in types)
if (hs.Add(ty.AssemblyQualifiedName))
{
IRunDataConverter converter = null;
try
{
converter = create(ty);
}
catch (Exception ex)
{
this.logger.LogError($"Cannot create IRunDataConverter! assemblyName: {ty.AssemblyQualifiedName} typeName: {ty.Name} exception: {ex.GetLogMessage()}");
}
if (converter != null)
{
if (this.converters.ContainsKey(converter.Key))
throw new Exception($"Duplicated key for IRunDataConverter! There can be only one converter for a key. Key: {converter.Key}");
else
this.converters.Add(converter.Key, converter);
}
}
}
private IRunDataConverter create(Type ty)
{
//ref: https://stackoverflow.com/a/34746583/1266873
return (IRunDataConverter)ActivatorUtilities.CreateInstance(this.provider, ty);
}
IRunDataPublishable[] IRunDataConverterManager.ConvertToPublishable(RunData[] data)
{
return this.getData(data).ToArray();
}
private IEnumerable<IRunDataPublishable> getData(RunData[] data)
{
Dictionary<string, List<object>> dic = new();
if (data != null)
foreach (RunData item in data)
if (item != null)
{
//this is where it's called
object value = this.converters.ContainsKey(item.Key) ? this.converters[item.Key].ConvertToPublishable(item.Value) : item.Value;
if (!dic.ContainsKey(item.Key))
dic.Add(item.Key, new List<object>() { value });
else
dic[item.Key].Add(value);
}
foreach (string key in dic.Keys)
yield return new runData()
{
Key = key,
Values = dic[key].ToArray()
};
}
private class runData : IRunDataPublishable
{
public string Key { get; set; }
public object[] Values { get; set; }
}
}
//RunData class is in another non-unsafe dll:
[DebuggerDisplay("Key: {Key} Value: {Value}")]
public class RunData
{
public RunnerNode Node { get; set; }
public string Key { get; set; }
public object Value { get; set; }
public RunDataDictionary Children { get; private set; } = new RunDataDictionary();
public RunData(RunnerNode node, string key, object value)
{
this.Node = node;
this.Key = key;
this.Value = value;
}
public RunData Clone()
{
return new RunData(this.Node, this.Key, this.Value)
{
Children = this.Children.Clone()
};
}
}
IRunDataConverterManager is a singleton injected item (Startup/ConfigureServices/
services.AddSingleton<IRunDataConverterManager, RunDataConverterManager>();)
RunData items, the values are not serialized-deserialized in any way, until the issue I'm facing in the BoxConverter.ConvertToPublishable method.