我有一个具有对象类型输入的函数。该函数的值是一个名为“Box”的类的数组,我已经进行了以下尝试,但无法转换 object value
至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;
}
}
当我输入typeof(Box)
时和arr[0].GetType()
进入立即窗口我得到以下结果。 (图中未见的部分是相同的。)
这是 Box 类:
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);
}
}
}
这种情况发生在 Visual Studio 2019、Windows 10 环境中 Entity Framework 和 Web API 项目使用的不安全 dll 内。所有项目的目标框架都是.NET 5.0。
更新 - 之前发生了什么:
IRunDataConverter 正在使用此管理器类进行调用。它位于非不安全的 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 是一个单例注入(inject)项(Startup/ConfigureServices/
services.AddSingleton<IRunDataConverterManager, RunDataConverterManager>();
)
RunData 项,这些值不会以任何方式序列化-反序列化,直到我在 BoxConverter.ConvertToPublishable
中遇到问题为止。方法。
最佳答案
请更改下面的代码。
AppDomain.CurrentDomain.Load(File.ReadAllBytes(dll)) -> AppDomain.CurrentDomain.Load(Assembly.LoadFrom(dll).GetName());
关于c# - 无法将对象转换为其类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67600330/