简体   繁体   English

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

[英]C# cast derived class to base class exception via reflection

I have an app that creates classes dynamically using reflection. 我有一个使用反射动态创建类的应用程序。 When deployed, I get an exception when casting a derived class to its base class. 部署时,在将派生类强制转换为基类时会出现异常。 It only happens on 1 in 100 machines. 它只发生在100台机器中的1台。 All the classes are in the same assembly. 所有类都在同一个程序集中。 Below are some code snippets and output from a logging message just prior to the casting exception. 下面是一些代码片段,并在转换异常之前从日志消息中输出。 I'm at my wits end, any help greatly appreciated. 我在我的智慧结束,任何帮助非常感谢。

//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;
        }
    }
}

Logging output on failed machine: 记录故障机器上的输出:

Message = Found assembly=Framework.DataModel, Version=1.0.5885.31486, Culture=neutral, PublicKeyToken=null Message = Found assembly = Framework.DataModel,Version = 1.0.5885.31486,Culture = neutral,PublicKeyToken = null

Message = newObj AssemblyQualifiedName=Framework.DataModel.CADElementRequest, Framework.DataModel, Version=1.0.5885.31486, Culture=neutral, PublicKeyToken=null, BaseType==Framework.DataModel.DataTreeRequest, FullName==Framework.DataModel.CADElementRequest Message = newObj AssemblyQualifiedName = Framework.DataModel.CADElementRequest,Framework.DataModel,Version = 1.0.5885.31486,Culture = neutral,PublicKeyToken = null,BaseType == Framework.DataModel.DataTreeRequest,FullName == Framework.DataModel.CADElementRequest

BaseException: Can't cast newObj to type DataTreeRequest. BaseException:无法将newObj强制转换为类型DataTreeRequest。 newObj = Name=Substations;InType=;InName=Substations;OutName=Substations;InSource=;OutSource=;, Type = Framework.DataModel.CADElementRequest newObj = Name = Subations; InType =; InName = Substations; OutName = Substations; InSource =; OutSource =;,Type = Framework.DataModel.CADElementRequest

try to replace 试着替换

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

Type requestType = asm.GetType(inType);

with

Type requestType = Type.GetType(inType)

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

If you need load assembly that is not referenced by project consider using Assembly.Load method. 如果需要未被项目引用的加载程序集,请考虑使用Assembly.Load方法。

About disadvantages of using Assembly.LoadFrom read Remarks section in https://msdn.microsoft.com/EN-US/library/1009fa28(v=VS.110,d=hv.2).aspx 关于使用Assembly.LoadFrom的缺点阅读https://msdn.microsoft.com/EN-US/library/1009fa28(v=VS.110,d=hv.2).aspx中的备注部分

the red flag is it fails on specific machines (1 out of 100) - how many machines in total does the code fail on? 红旗是否在特定机器上失败(100个中的1个) - 代码总共有多少台机器失败? This indicates that it might be the configuration of the machine rather than the code. 这表明它可能是机器的配置而不是代码。 It also makes it extremely difficult to replicate in order to help. 它也使复制起来非常困难以帮助。

If it were me. 如果是我。 I'd take a step back and simplify the situation. 我退后一步,简化情况。 Write code that just does the failing task, even with other simpler classes, and then focus on a failing machine. 编写只执行失败任务的代码,即使是其他更简单的类,然后专注于失败的机器。 Get as much information as possible and build up understanding. 获取尽可能多的信息并建立理解。

It's likely to be referent pain. 这可能是指称痛苦。 The situation your facing is only a symptom of the real problem. 你面临的情况只是真正问题的症状。 You're focused on the code but that's just a symptom. 你专注于代码,但这只是一个症状。 That's why it would be good to simplify. 这就是为什么简化会很好的原因。

Hope this helps, I'm new to stackoverflow and I know there are rules to follow for questions. 希望这会有所帮助,我是stackoverflow的新手,我知道有一些规则要遵循问题。 I'd have made this a comment but I don't have the reputation for that. 我已经发表了评论,但我没有这个名声。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM