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

时间:2016-02-13 15:29:59

标签: c# .net

我有一个使用反射动态创建类的应用程序。部署时,在将派生类强制转换为基类时会出现异常。它只发生在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;
        }
    }
}

在故障机器上记录输出:

  

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,   全名== Framework.DataModel.CADElementRequest

     

BaseException:无法将newObj强制转换为类型DataTreeRequest。 newObj =   名称=变电站;法菜单=; InName =变电站; OutName =变电站;内购=;外包= ;,   Type = Framework.DataModel.CADElementRequest

2 个答案:

答案 0 :(得分:1)

尝试替换

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

中的备注部分

答案 1 :(得分:0)

红旗是否在特定机器上失败(100个中的1个) - 代码总共有多少台机器失败?这表明它可能是机器的配置而不是代码。它也使复制起来非常困难,以便提供帮助。

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

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

希望这会有所帮助,我是stackoverflow的新手,我知道有一些规则要遵循问题。我已经发表了评论,但我没有这个名声。