Tags: , | Categories: Blog Posted by al on 7/29/2010 4:22 PM | Comments (2)

Update 7/29/2010:

Actually I found my problem I think, when referencing any of this 2 dlls I get into the error described.

System.Windows.Controls.Data.Toolkit.dll

System.Windows.Controls.Toolkit.dll

I don't need to use them, just for the fact to be reference, MEF will roll over and die.

Hope this helps

MEF is great technology yet, looks still a little young and without much documentation for my personal taste. There are a few samples, however, when you are trying to go beyond what is provided you can get in a huge amount of troubles with a generic error:

I found that trying to load just one xap file was giving me this error:

[System.InvalidOperationException] = {System.InvalidOperationException: The package downloaded successfully but an error occurred while reading the contents of the package. See the inner exception for more details. ---> System.Reflection.ReflectionTypeLoadException: Unable to load one or more ...

Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.RuntimeModule.GetTypes()
at System.Reflection.Assembly.GetTypes()
at System.ComponentModel.Composition.Hosting.AssemblyCatalog.get_InnerCatalog()
at System.ComponentModel.Composition.Hosting.AssemblyCatalog.get_Parts()
at System.ComponentModel.Composition.Hosting.DeploymentCatalog.DiscoverParts(IEnumerable`1 assemblies)
at System.ComponentModel.Composition.Hosting.DeploymentCatalog.HandleOpenReadCompleted(Object sender, OpenReadCompletedEventArgs e)

Just by doing this

              var catalog = new AggregateCatalog();

                catalog.Catalogs.Add(CreateCatalog("something.xap"));

                CompositionHost.Initialize(new DeploymentCatalog(), catalog);
                CompositionInitializer.SatisfyImports(this);
        private DeploymentCatalog CreateCatalog(string uri)
        {
            var catalog = new DeploymentCatalog(uri);
            catalog.DownloadCompleted += (s, e) => DownloadCompleted(s,e);
            catalog.DownloadAsync();
            return catalog;
        }

        private void DownloadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
        }

If I changed the second line for a dot, MEF now load all the xaps in that directory, that by default is ClientBin

catalog.Catalogs.Add(CreateCatalog("."));

The samples on the MEF codeplex website have a few syntax error for DeploymentCatalog

http://mef.codeplex.com/wikipage?title=DeploymentCatalog

I fixed it to the best of my knowledge.

public interface IDeploymentCatalogService
    {
        void AddXap(string relativeUri, Action<AsyncCompletedEventArgs> completedAction);
    }

    [Export(typeof(IDeploymentCatalogService))]
    public class DeploymentCatalogService : IDeploymentCatalogService
    {
        private static AggregateCatalog _aggregateCatalog;

        Dictionary<string, DeploymentCatalog> _catalogs;

        public DeploymentCatalogService()
        {
            _catalogs = new Dictionary<string, DeploymentCatalog>();
        }

        public static void Initialize()
        {
            _aggregateCatalog = new AggregateCatalog();
            _aggregateCatalog.Catalogs.Add(new DeploymentCatalog());
            CompositionHost.Initialize(_aggregateCatalog);
        }

        public void AddXap(string relativeUri, Action<AsyncCompletedEventArgs> completedAction)
        {
            DeploymentCatalog catalog;
            if (!_catalogs.TryGetValue(relativeUri, out catalog))
            {
                catalog = new DeploymentCatalog(relativeUri);

                if (completedAction != null)
                    catalog.DownloadCompleted += (s, e) => completedAction(e);
                else
                    catalog.DownloadCompleted += (s, e) => DownloadCompleted(s, e);

                catalog.DownloadAsync();
                _catalogs[relativeUri] = catalog;
                _aggregateCatalog.Catalogs.Add(catalog);
            }
        }

        void DownloadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                throw new InvalidOperationException(e.Error.Message, e.Error);
            }
        }
    }

 

Now I want to load xap files without having to know what type there are, I found this great blog post from Glenn Block (Mr. MEF) where provides a Widget project to load them in MEF http://codebetter.com/blogs/glenn.block/archive/2010/03/07/building-hello-mef-part-iv-deploymentcatalog.aspx?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+CodeBetter+%28CodeBetter.Com%29

Glenn provided a better way to load xap files, just using this 3 lines of code:

DeploymentCatalogService.Initialize();
CompositionInitializer.SatisfyImports(this);

CatalogService.AddXap("HelloMEF.Extensions.xap");

Using his example shall work to load UserControls, now I tried to modify to load ResourceDictionary by changing the MEF attribute to:

    [MetadataAttribute]
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class ExportThemeAttribute : ExportAttribute
    {
        public ExportThemeAttribute()
            : base(typeof(ResourceDictionary))
        {
        }

        public WidgetLocation Location { get; set; }
    }

To receive the error again: The package downloaded successfully but an error occurred while reading the contents of the package.

I made sure there wasn’t any circular reference and the metadata was like the sample provided and still didn’t had any success.

 

How can I load a xap containing other resources besides UserControls?

Cheers

Al

blog comments powered by Disqus