C# 通过反射将派生类强制转换为基类异常

本文关键字:转换 基类 异常 反射 派生 | 更新日期: 2023-09-27 18:34:25

我有一个使用反射动态创建类的应用程序。部署时,在将派生类强制转换为其基类时出现异常。 它只发生在 100 台机器中的 1 台上。所有类都位于同一程序集中。下面是转换异常之前日志记录消息的一些代码片段和输出。我处于智慧的尽头,非常感谢任何帮助。

//Parent class
namespace Framework.DataModel
{
    [Serializable]
    public class DataTreeRequest : TreeNode, IDirtyListener, ISerializable
    {
        ....
    }
}
// Derived Class    
namespace Framework.DataModel
{
    [Serializable]
    public class CADElementRequest : DataTreeRequest
    {
        public CADElementRequest(String name) : base(name){}
    }
}

// Method that uses reflection to create class and then cast to its base class
namespace Framework.DataModel
{
    [Serializable]
    public class DataModelBuilder : CoreBuilder
    {
        ...
        protected DataTreeRequest CreateDataTreeRequest(String asmName, String inName, String inType, String inSourceName)
        {
            DataTreeRequest dtr = null;
            Assembly asm = Assembly.LoadFrom(asmName);
            if (asm == null)
            {
                throw new BaseException("Can't find assembly " + asmName);
            }
            Type requestType = asm.GetType(inType);
            if (requestType == null)
            {
                throw new BaseException("Can't find class of type " + inType + " in assembly " + asmName);
            }
            // Call the constructor for the tree node that takes the xml node as an argument
            Type[] constructorArgsTypes = new Type[1];
            constructorArgsTypes[0] = typeof(String);
            ConstructorInfo constructorInfo = requestType.GetConstructor(constructorArgsTypes);
            if (constructorInfo == null)
            {
                throw new BaseException("Can't find constructor for type " + inType + " that takes a String param");
            }
            Object[] constructorArgs = new Object[1];
            constructorArgs[0] = inName;
            Object newObj = constructorInfo.Invoke(constructorArgs);
            // Code fails on this line trying to cast derived class to base class on 1 in 100 machines
            dtr = newObj as DataTreeRequest;
            if (dtr == null)
            {
                throw new BaseException("Can't cast newObj to type DataTreeRequest. newObj = " + newObj + ", Type = " + newObj.GetType().ToString());
            }
            dtr.InSource = inSourceName;
            return dtr;
        }
    }
}

故障计算机上的日志记录输出:

消息 = 找到程序集=框架.数据模型,版本=1.0.5885.31486, 区域性=中性,公钥令牌=空

消息 = 新对象 AssemblyQualifiedName=Framework.DataModel.CADElementRequest, Framework.DataModel, Version=1.0.5885.31486, Culture=neutral, PublicKeyToken=null, BaseType==Framework.DataModel.DataTreeRequest, FullName==Framework.DataModel.CADElementRequest

BaseException:无法将 newObj 转换为数据类型 DataTreeRequest。 newObj = 名称=变电站;InType=;InName=变电站;OutName=Substation;InSource=;OutSource=;, Type = Framework.DataModel.CADElementRequest

C# 通过反射将派生类强制转换为基类异常

尝试替换

Assembly asm = Assembly.LoadFrom(asmName);
if (asm == null)
{
    throw new BaseException("Can't find assembly " + asmName);
}
Type requestType = asm.GetType(inType);

Type requestType = Type.GetType(inType)

其中 inType 是程序集限定名称https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110(.aspx

如果需要加载项目未引用的程序集,请考虑使用 Assembly.Load 方法。

关于使用 Assembly.LoadFrom 的缺点,请阅读 https://msdn.microsoft.com/EN-US/library/1009fa28(v=VS.110,d=hv.2( 中的备注部分.aspx

危险信号是它在特定机器上失败(100 台中有 1 台(- 代码总共在多少台机器上失败?这表明这可能是计算机的配置而不是代码。这也使得为了提供帮助而复制变得极其困难。

如果是我。我会退后一步,简化情况。编写只执行失败任务的代码,即使使用其他更简单的类,然后专注于失败的计算机。获取尽可能多的信息并建立理解。

这很可能是指涉性疼痛。你所面临的情况只是真正问题的症状。您专注于代码,但这只是一个症状。这就是为什么简化会很好。

希望这有所帮助,我是堆栈溢出的新手,我知道有问题需要遵循的规则。我会对此发表评论,但我没有这方面的声誉。