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

本文关键字:异常 ctor ImportingConstructor 处理 使用 | 更新日期: 2023-09-27 18:32:44

下面是两个类,其中一个使用ImportingConstructor导入另一个类,并直接从ctor抛出MyException。所以,我希望在另一个类中捕获MyException,但我得到了另一个,即:

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

如何强制 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){...}
}

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

AFAIK,您无法让 MEF 抛出原始异常,但如果挖掘,原始异常在堆栈跟踪中。因此,处理此问题的一种方法是检查CompositionException中是否存在预期的异常。如果找到它,则可以继续所需的错误处理。

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

根据引发异常的位置,可能取决于您需要在堆栈跟踪中查找的位置,但上面的简单示例应该可以让您走上正确的道路。如果您有兴趣,这里是 MSDN 文档

为了完整起见,这里是完整的实现

[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
            }
        }
    }
}