【问题标题】:Handle an exception thrown from ctor with ImportingConstructor使用 ImportingConstructor 处理 ctor 抛出的异常
【发布时间】:2014-12-02 14:42:38
【问题描述】:

下面是两个类,其中一个使用 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){...}
}

【问题讨论】:

    标签: c# mef


    【解决方案1】:

    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 docs

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

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

    【讨论】:

    • 是的,你说得对。 CompositionException 包含有关原因的信息,但我得到 InvalidOperationException,因此无法提取任何其他数据。
    • @AndrewOrlov:是的,我敢打赌你看到的异常不是源自class1 构造函数。您可以发布一些复制错误的代码吗?我个人唯一一次看到该异常来自多线程应用程序。您提供的示例代码不会复制您遇到的问题,它会抛出 CompositionException
    • 是的,我看到 System.TypeInitializationException 带有一般消息,例如 The type initializer for 'Class2' throw an exception。
    • 很遗憾,我无法提供源代码,因为它是企业项目。
    • @AndrewOrlov:是的,我希望您无法显示原始来源,但我希望有一个显示异常的模型。不幸的是,如果不能看到正在发生的事情,我认为我不会有太大帮助,但也许其他人会认识到这个问题。您可能已经遇到过这个问题,但是这个SO Question 可能与TypeInitializationException 相关
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 2011-10-10
    • 2011-11-23
    • 1970-01-01
    • 1970-01-01
    • 2013-06-08
    相关资源
    最近更新 更多