简体   繁体   English

使用ImportingConstructor处理从ctor引发的异常

[英]Handle an exception thrown from ctor with ImportingConstructor

Here below are two classes where one of them is importing another one using ImportingConstructor and throws an MyException right from ctor. 下面是两个类,其中一个使用ImportingConstructor导入另一个,并从ctor引发MyException。 So, I expect to catch MyException in another class, but I get quite another one, namely: 因此,我希望在另一个类中捕获MyException,但是我得到了另一个类,即:

 System.InvalidOperationException: GetExportedValue cannot be called before prerequisite import 'Class1..ctor ' has been set. (...)

How can I force the MEF to throw an original exception, or at least to wrap original one to some exception, so I could to handle it from my code? 如何强制MEF引发原始异常,或者至少将原始异常包装为某种异常,以便可以从代码中处理它?

[Export]
class Class1
{
    public Class1()
    {
       (....)
       throw new MyException("MyException has been thrown");
    }
}

class Class2
{
    [ImportingConstructor]
    public Class2(Class1 class1)
    {
        (....)
    }
}

static void Main(string[] args)
{
    var catalog = new AggregateCatalog(
        new AssemblyCatalog(typeof (Class1).Assembly));
    CompositionContainer container = new CompositionContainer(catalog, true);
    try{
      Class2 class2 = container.GetExportedValue<Class2>();
    }
    catch(MyException ex){...}
}

AFAIK, you cannot get MEF to throw the original exception, but the original exception is within the stack trace if you dig. AFAIK,您不能使MEF引发原始异常,但是如果进行挖掘,则原始异常在堆栈跟踪中。 So one way to handle this would be to inspect the CompositionException for the exception you expected. 因此,处理此问题的一种方法是检查CompositionException以获取您期望的异常。 If you find it, then you can continue with the error handling you need. 如果找到它,则可以继续进行所需的错误处理。

try
{
    Class2 class2 = container.GetExportedValue<Class2>();
}
catch (CompositionException ex)
{
    foreach (var cause in ex.RootCauses)
    {
        //Check if current cause is the Exception we're looking for
        var myError = cause as MyException;

        //If it's not, check the inner exception (chances are it'll be here)
        if (myError == null)
            myError = cause.InnerException as MyException;

        if (myError != null)
        {
            //do what you want
        }
    }
}

Depending on where the exception is thrown may depend on where you need to look in the stack trace, but the simple example above should get you down the right path. 根据引发异常的位置,可能取决于您需要在堆栈跟踪中查找的位置,但是上面的简单示例将使您走上正确的道路。 In case you're interested, here's the MSDN docs 如果您有兴趣,这里是MSDN文档

For completeness, here's the full implementation 为了完整起见,这是完整的实现

[Export]
class Class1
{
    public Class1()
    {
        throw new MyException("MyException has been thrown");
    }
}

[Export]
class Class2
{
    [ImportingConstructor]
    public Class2(Class1 class1)
    {

    }
}

static void Main(string[] args)
{
    var catalog = new AggregateCatalog(
        new AssemblyCatalog(typeof (Class1).Assembly));
    CompositionContainer container = new CompositionContainer(catalog, true);
    try
    {
        Class2 class2 = container.GetExportedValue<Class2>();
    }
    catch (CompositionException ex)
    {
        foreach (var cause in ex.RootCauses)
        {
            var myError = cause as MyException;

            if (myError == null)
                myError = cause.InnerException as MyException;

            if (myError != null)
            {
                //do what you want
            }
        }
    }
}

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

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