简体   繁体   English

VS2010 / .Net 4的新强制转换例外

[英]New cast exception with VS2010/.Net 4

[ Updated 25 May 2010 ] I've recently upgraded from VS2008 to VS2010, and at the same time upgraded to .Net 4. [2010年5月25日更新]我最近从VS2008升级到VS2010,同时又升级到.Net 4。

I've recompiled an existing solution of mine and I'm encountering a Cast exception I did not have before. 我已经重新编译了我现有的解决方案,并且遇到了以前没有的Cast异常。

The structure of the code is simple (although the actual implementation somewhat more complicated). 代码的结构很简单(尽管实际实现有些复杂)。

Basically I have: 基本上我有:

public class SomeClass : ISomeClass
{
 // Stuff
}

public static class ClassFactory
{
  public static IInterface GetClassInstance<IInterface>(Type classType)
  {
     return (IInterface)Activator.CreateInstance(classType); // This throws a cast exception
  }
}

// Call the factory with:

ISomeClass anInstance = ClassFactory.GetClassInstance<ISomeClass>(typeof(SomeClass));

Ignore the 'sensibleness' of the above - its provides just a representation of the issue rather than the specifics of what I'm doing (eg constructor parameters have been removed). 忽略上面的“敏感性”-它仅提供问题的表示,而不是我正在做的事情的细节(例如,构造函数参数已删除)。

The marked line throws the exception: 标记的行引发异常:

Unable to cast object of type 'Namespace.SomeClass' to type 'Namespace.ISomeClass'. 无法将类型为“ Namespace.SomeClass”的对象转换为类型为“ Namespace.ISomeClass”的对象。

I suspect it may have something to do with the additional DotNet security (and in particular, explicit loading of assemblies, as this is something my app does). 我怀疑这可能与附加的DotNet安全性有关(尤其是显式加载程序集,因为这是我的应用程序所做的事情)。

The reason I suspect this is that I have had to add to the config file the setting: 我怀疑这是因为我必须将设置添加到配置文件中:

<runtime>
    <loadFromRemoteSources enabled="true" />
</runtime>

.. but I'm unsure if this is related. ..但我不确定这是否相关。

Update 更新资料

I see (from comments) that my basic code does not reproduce the issue by itself. 我(从评论中)看到我的基本代码本身无法重现该问题。 Not surprising I suppose. 我想不足为奇。 It's going to be tricky to identify which part of a largish 3-tier CQS system is relevant to this problem. 识别较大的3层CQS系统的哪个部分与该问题有关将非常棘手。

One issue might be that there are multiple assemblies involved. 一个问题可能是涉及多个程序集。 My static class is actually a factory provider, and the 'SomeClass' is a class factory (relevant in that the factories are 'registered' within the app via explicit assembly/type loading - see below) . 我的静态类实际上是一个工厂提供程序,而'SomeClass'是一个类工厂(相关的工厂通过显式程序集/类型加载在应用程序内“注册”,请参见下文)。

Upfront I use reflection to 'register' all factories (ie classes that implement a particular interface) and that I do this when the app starts by identifying the relevant assemblies, loading them and adding them to a cache using (in essence): 预先,我使用反射来“注册”所有工厂(即实现特定接口的类),并且在应用程序启动时通过标识相关程序集,加载它们并将它们添加到缓存中(实质上)来执行此操作:

Loop over (file in files)
{
    Assembly assembly = Assembly.LoadFile(file);
    baseAssemblyList.Add(assembly);
}

Then I cache the available types in these assemblies with: 然后,我在这些程序集中缓存可用类型:

foreach (Assembly assembly in _loadedAssemblyList)
{
  Type[] assemblyTypes = assembly.GetTypes();
  _loadedTypesCache.AddRange(assemblyTypes);
}

And then I use this cache to do a variety of reflection operations, including 'registering' of factories, which involves looping through all loaded (cached) types and finding those that implement the (base) Factory interface. 然后,我使用此缓存执行各种反射操作,包括工厂的“注册”,这涉及遍历所有已加载(缓存的)类型并查找实现(基本)Factory接口的类型。

I've experienced what may be a similar problem in the past (.Net 3.5, so not exactly the same) with an architecture that involved dynamically creating classes on the server and streaming the compiled binary of those classes to the client app. 我过去曾遇到过类似的问题(.Net 3.5,所以不完全相同),该体系结构涉及在服务器上动态创建类并将这些类的编译后的二进制流传输到客户端应用程序。 The problem came when trying to deserialize an instance of the dynamic class on the client from a remote call: the exception said the class type was not know, even though the source and destination types were exactly the same name (including namespace). 尝试通过远程调用在客户端上反序列化动态类的实例时出现问题:异常表明类类型是未知的,即使源和目标类型的名称完全相同(包括名称空间)。 Basically the cross boundry versions of the class were not recognised as being the same. 基本上,该类的跨界版本不被认为是相同的。 I solved that by intercepting the deserialization process and explicitly defining the deseriazation class type in the context of the local assemblies. 通过拦截反序列化过程并在本地程序集的上下文中显式定义反序列化类类型,我解决了这一问题。

This experience is what makes me think the types are considered mismatched because (somehow) the interface of the actual SomeClass object, and the interface of passed into the Generic method are not considered the same type. 这种经历使我认为类型被认为是不匹配的,因为(某种程度上)实际SomeClass对象的接口和传递给Generic方法的接口不被视为同一类型。

So (possibly) my question for those more knowledgable about C#/DotNet is: How does the class loading work that somehow my app thinks there are two versions/types of the interface type and how can I fix that (keeping in mind its a DotNet 3.5 vs 4 issue as it worked before my upgrade) ? 因此(可能)对于那些更了解C#/ DotNet的人来说,我的问题是:类加载如何工作,以某种方式我的应用程序认为接口类型有两种版本/类型,我该如何解决(记住它的DotNet 3.5 vs 4问题,因为它在我升级之前有效)?

[ whew ... anyone who got here is quite patient .. thanks ] [哇...到这里的人都很耐心..谢谢]

I would say yes that it has something to do either with the runtime loading of assemblies, or with the upgrade conversion, I used this code in a new project and had no issues. 我会说是的,它与程序集的运行时加载或升级转换有关,我在新项目中使用了此代码,没有任何问题。 Can you provide more code to replicate the error? 您可以提供更多代码来复制错误吗?

The 'quick' (ITO implementation, not ITO finding it) solution was to stop the shadow copy of my app's DLLs. “快速”(ITO实现,而不是ITO找到它)解决方案是停止我应用程序DLL的卷影副本。 This is done by modifying the ASP.Net app's Web.Config file as follows: 这是通过如下修改ASP.Net应用程序的Web.Config文件来完成的:

In section 'configuration/web.settings', add setting: 在“配置/web.settings”部分中,添加设置:

<hostingEnvironment shadowCopyBinAssemblies="false" />

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

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