質問

I am working with MEF to load modules from different sources into my app. I have an example (code below) where I create a class that is composable which throws an exception in the constructor. That exception causes the composition to fail and thus throw an exception that says "why"... In the statement it says that the cause is an InvalidCastException... which is true.

If I print the exception, I know why it fails, but how do I retrieve the ACTUAL original exception (InvalidCastException) thrown, in order for me to handle it properly -- rather than just a generic catch, which would miss other exceptions -- in the module that is asking for an instance of the said class? Querying the CompositionException.Errors doesn't give me the original exception either...

CODE:

using System.ComponentModel.Composition;
using Microsoft.Practices.ServiceLocation;

[Export(typeof(A))]
Class A
{
    [ImportingConstructor]
    public A(ISomeinterface x, ISomeOtherInterface y)
    {
        //// Throw some exception (in my code it happens to be an InvalidCastException)
        throw new InvalidCastException ("Unable to cast object of type 'Sometype' to type 'Someothertype'.");  
    }
}

Class B
{
    public B(IServiceLocator serviceLocator)
    {
        try
        {
            //// Here is where the exception would be thrown as an "ActivationException"
            A myAInstance = serviceLocator.GetInstance(A);
        }
        catch (ActivationException activationException)
        {
            //// Print original activation exception from trying to get the service
            System.Diagnostics.Debug.WriteLine(activationException);

            if (ex.InnerException is CompositionException)
            {
                CompositionException compositionException = (CompositionException)activationException.InnerException;

                //// *** Here is where I want to retrieve the InvalidCastException in order to handle it properly
                //// *** Also, componentException.InnerException is "null" and so is the componentException.Errors[0].Exception.InnerException 
            }
            else
            {
                throw;
            }
        }
    }
}

OUTPUT:

Microsoft.Practices.ServiceLocation.ActivationException: Activation error occured while trying to get instance of type A, key "" ---> System.ComponentModel.Composition.CompositionException: The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.

1) Unable to cast object of type 'Sometype' to type 'Someothertype'.

Resulting in: An exception occurred while trying to create an instance of type 'A'.

Resulting in: Cannot activate part 'A'.
Element: A -->  A -->  DirectoryCatalog (Path="C:\path\to\code\")

Resulting in: Cannot get export 'A (ContractName="A")' from part 'A'.
Element: A (ContractName="A") -->  A -->  DirectoryCatalog (Path="C:\path\to\code\")

   at System.ComponentModel.Composition.Hosting.CompositionServices.GetExportedValueFromComposedPart(ImportEngine engine, ComposablePart part, ExportDefinition definition)
   at System.ComponentModel.Composition.Hosting.CatalogExportProvider.GetExportedValue(CatalogPart part, ExportDefinition export, Boolean isSharedPart)
   at System.ComponentModel.Composition.ExportServices.GetCastedExportedValue[T](Export export)
   at System.ComponentModel.Composition.ExportServices.<>c__DisplayClass10`2.<CreateSemiStronglyTypedLazy>b__d()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Microsoft.Practices.Prism.MefExtensions.MefServiceLocatorAdapter.DoGetInstance(Type serviceType, String key) in c:\release\WorkingDir\PrismLibraryBuild\PrismLibrary\Desktop\Prism.MefExtensions\MefServiceLocatorAdapter.cs:line 73
   at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key)
   --- End of inner exception stack trace ---
   at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key)
   at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance[TService]()
   at <code> line whatever...
System.ComponentModel.Composition.CompositionException: The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
役に立ちましたか?

解決

I found the solution the actual exception is nested deep in the compositionException.Errors hierarchy. One would think the original exception would be under the original composition exception but actually this is how to access it:

It happens to be the innerexception inside one of the errors of another composition exception which is itself one of the errors in the original composition exception

CompositionException compositionException = (CompositionException)activationException.InnerException;
CompositionException innerCompositionException = compositionException.Errors[0].Exception;
InvalidCastException castException = (InvalidCastException)innerCompositionException.Errors[0].Exception.InnerException

I won't delete this in case someone else runs into the same thing.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top