C# try/catch未捕获TypeLoadException
为了演示,我试图重新创建一个C# try/catch未捕获TypeLoadException,c#,type-safety,typeloadexception,C#,Type Safety,Typeloadexception,为了演示,我试图重新创建一个TypeLoadException,所以我有一个可笑的库设置,看起来像这样: TestProject --> TheLibrary [1.0] \-> ProxyForV2 -> TheLibrary [2.0] 图书馆版本1具有以下相关接口: public interface IConsistentThing { int ConsistentProperty { get; set; } } public inte
TypeLoadException
,所以我有一个可笑的库设置,看起来像这样:
TestProject --> TheLibrary [1.0]
\-> ProxyForV2 -> TheLibrary [2.0]
图书馆
版本1具有以下相关接口:
public interface IConsistentThing
{
int ConsistentProperty { get; set; }
}
public interface IShrinkingThing
{
int RemovedProperty { get; set; }
}
而库的第2版的接口如下所示:
public interface IConsistentThing
{
int ConsistentProperty { get; set; }
}
public interface IShrinkingThing
{ }
ProxyForV2
有一个类,它实现了2.0版IShringThing
:
public class ShrinkingThingImpl : IShrinkingThing
{
public int ConsistentProperty { get; set; }
}
因此,在TestProject
中,如果有人试图为v2.ShrinkingThingImpl分配ProxyForV2.ShrinkingThingImpl
,我希望会导致TypeLoadException
,因为接口的第一个版本具有第二个版本未实现的属性。为了证明这一点,我做了一个单元测试,如下所示:
[TestMethod]
public void ShrinkingThingBreaks()
{
try
{
IShrinkingThing thing = new ProxyForV2.ShrinkingThingImpl();
Assert.Fail("This should have caused a TypeLoadException");
}
catch (TypeLoadException)
{
// valid
}
}
我的问题是:这个单元测试失败了。但这并不是由于我的Assert.Fail
,正如我所期望的那样。测试输出如下所示:
TestProject --> TheLibrary [1.0]
\-> ProxyForV2 -> TheLibrary [2.0]
测试方法TestProject.LoadTester.ShrinkingThingBreaks引发异常:System.TypeLoadException:程序集“ProxyForV2,版本=1.0.0.0,区域性=中性,PublicKeyToken=null”中类型为“ProxyForV2.ShrinkingThingImpl”的方法“get\u RemovedProperty”没有实现
因此,正在抛出一个TypeLoadException
,尽管它唯一可能被抛出的位置是在带有catch(TypeLoadException)
的try
块中,但异常拒绝被捕获。除此之外,即使我使用了一个catch all,单元测试也会失败,错误与之前相同:
[TestMethod]
public void ShrinkingThingBreaks()
{
try
{
IShrinkingThing thing = new ProxyForV2.ShrinkingThingImpl();
Assert.Fail("This should have caused a TypeLoadException");
}
catch
{
// valid
}
}
发生了什么事?显然,这是一个完全人为设计的场景,但我仍然想知道发生了什么,以便在运行时避免这个错误,或者至少在发生错误时处理它(是的,我知道最终的解决方案是确保所有库版本都相同)
最糟糕的是,对该类的任何访问,例如typeof(ProxyForV2.ConsistentThingImpl)
或ProxyForV2.ConsistentThingImpl.SomeStaticFunction()
都会导致此不可捕获的TypeLoadException
,因此很明显,当.NET尝试加载该类时会产生问题,不是因为任何任务
我缓解这个问题的唯一想法是尝试在不同的应用程序域中加载类型,这样它就不会干扰,然后做一些疯狂的反射工作,看看接口是否与实现兼容,但这似乎是完全的、完全的过火了
总而言之:为什么用“正常”的方式似乎不可能捕捉到这个问题?我如何在运行时解决这样的问题?类型在使用它们的方法开始执行之前被加载。为此,您需要:
[TestMethod]
public void ShrinkingThingBreaks()
{
try
{
InnerShrinkingThingBreaks();
Assert.Fail("This should have caused a TypeLoadException");
}
catch
{
// valid
}
}
[MethodImpl(MethodImplAttributes.NoInlining)]
private void InnerShrinkingThingBreaks()
{
IShrinkingThing thing = new ProxyForV2.ShrinkingThingImpl();
}
对此不完全确定,所以只发表评论。。。单元测试的类型不都是预先加载的吗?因此,TypeLoadException实际上是在您到达try/catch块之前抛出的。我不知道你怎么能测试这个…在这个类中还有其他的单元测试通过得很好。如果您的意思是在方法调用时加载方法中使用的类型,那么这可能是issue.Works的根源。它也可以通过对lambda函数执行相同的操作来工作。@TravisGockel有没有使用lamda函数的示例?@Kiquenet:因为已经4年了,我记不清了,但我认为在try
块中,我说了这样的话:Action f=delegate(){var x=new ProxyForV2.ShrinkingThingImpl();};f()代码>@TravisGockel关于lamba函数的绝妙提示!它可以让你实现一个内联解决方案;这解释了为什么我的静态构造函数会抛出异常,尽管我用try-catch包住了其中的所有内容!我知道在静态构造函数中执行太多操作是不好的,现在我有了一个额外的理由来避免在这种情况下进行“复杂”的初始化。。。