How to Release Shared instances ?

Jan 19, 2011 at 5:42 PM
Edited Jan 19, 2011 at 5:51 PM

In my Silverlight application, when a user logs in, MEF creates instances of views and viewmodels "on demand" when the user clicks on a button, for example. But some views and viewmodels are dynamically populated with data based on roles of the logged user, and some variables related to this logged user.

 

I would like that MEF release that instances of views and viewmodels when the user do logout and recreates again on the demand when another user logs in. I tried to do as following:

 

 

void AuthenticationLoggedOut(object sender, System.ServiceModel.DomainServices.Client.ApplicationServices.AuthenticationEventArgs e)
        {
            AppUtils.ReleaseAllExports();
        }

public static void ReleaseAllExports()
        {
            var allExports = new List<Export>();

            var telaexports = CatalogoMef.GetContainer.GetExports<ITela>();
            foreach (var telaexport in telaexports)
            {
                if (telaexport.IsValueCreated)
                    allExports.Add(telaexport.Value as Export);
            }

            var telaviewmodelexports = CatalogoMef.GetContainer.GetExports<ITelaViewModel>();
            foreach (var telaviewmodelexport in telaviewmodelexports)
            {
                if (telaviewmodelexport.IsValueCreated)
                    allExports.Add(telaviewmodelexport.Value as Export);
            }

            CatalogoMef.GetContainer.ReleaseExports(allExports);
        }

But when debugging, the "allExports" variable contains null references and it appears that is not working.

Is there a better way to do this?

 

 

Jan 25, 2011 at 3:16 PM

Are you using nested containers?

Is GetExports returning no items?

I'd check that you're in the right container, then do nomral missing parts debugging as a start.

Feb 9, 2011 at 3:54 AM

this is the CatalogMef class.

I guess I'm not using nested containers.

 

public class CatalogoMef
    {
        #region "Private Data Members"
        private static readonly AggregateCatalog AggregateCatalog;
        private static readonly CompositionContainer Container;
        private static readonly CatalogoMef Instance;
        private readonly Dictionary<string, DeploymentCatalog> _catalogs;

        #endregion "Private Data Members"

        #region "Constructors and Initialize()"
        /// <summary>
        /// Default constructor
        /// </summary>
        private CatalogoMef()
        {
            _catalogs = new Dictionary<string, DeploymentCatalog>();
            CompositionInitializer.SatisfyImports(this);
        }

        /// <summary>
        /// Static constructor
        /// </summary>
        static CatalogoMef()
        {
            AggregateCatalog = new AggregateCatalog();
            AggregateCatalog.Catalogs.Add(new DeploymentCatalog());
            Container = new CompositionContainer(AggregateCatalog);
            CompositionHost.Initialize(Container);

            Instance = new CatalogoMef();
        }

        /// <summary>
        /// Initialize Method
        /// </summary>
        public static void Initialize()
        {
        }
        #endregion "Constructors and Initialize()"

        #region "Public Properties"

        public static CatalogoMef GetCatalogoMefInstance
        {
            get
            {
                return Instance;
            }
        }

        public static CompositionContainer GetContainer
        {
            get
            {
                return Container;
            }
        }

        #endregion "Public Properties"

        #region "Public Methods for Add & Remove Xap"

        public void AddCatalog(AssemblyCatalog assemblyCatalog)
        {
            AggregateCatalog.Catalogs.Add(assemblyCatalog);
        }

        public void RemoveCatalog(AggregateCatalog aggregateCatalog)
        {
            AggregateCatalog.Catalogs.Remove(aggregateCatalog);
        }


        public void AddXap(string uri, Action<AsyncCompletedEventArgs> completedAction = null, Action<DownloadProgressChangedEventArgs> downloadProgress = null)
        {
            DeploymentCatalog catalog;
            if (!_catalogs.TryGetValue(uri, out catalog))
            {
                catalog = new DeploymentCatalog(uri);
                catalog.DownloadCompleted += (s, e) =>
                {
                    if (e.Error != null)
                    {
                        throw new Exception(e.Error.Message, e.Error);
                    }
                    _catalogs.Add(uri, catalog);
                    AggregateCatalog.Catalogs.Add(catalog);
                };

                if (completedAction != null)
                    catalog.DownloadCompleted += (s, e) => completedAction(e);
                if (downloadProgress != null)
                {
                    catalog.DownloadProgressChanged += (s, e) => downloadProgress(e);
                }


                catalog.DownloadAsync();
            }
            else
            {
                if (completedAction != null)
                {
                    var e = new AsyncCompletedEventArgs(null, false, null);
                    completedAction(e);
                }
            }
        }

        /// <summary>
        /// Method to remove XAP
        /// </summary>
        /// <param name="uri"></param>
        public void RemoveXap(string uri)
        {
            DeploymentCatalog catalog;
            if (_catalogs.TryGetValue(uri, out catalog))
            {
                AggregateCatalog.Catalogs.Remove(catalog);
                _catalogs.Remove(uri);
            }
        }

        #endregion "Public Methods for Add & Remove Xap"

        public static T GetInstance<T>(string contract = null)
        {
            //he default behavior in MEF is to treat exports as singletons
            //[Export]()
            //[PartCreationPolicy(CreationPolicy.NonShared)]
            return !string.IsNullOrEmpty(contract) ? Container.GetExportedValueOrDefault<T>(contract) : Container.GetExportedValueOrDefault<T>();
        }
        public static IEnumerable<T> GetMultipleInstances<T>(string contract = null)
        {
            return !string.IsNullOrEmpty(contract) ? Container.GetExportedValues<T>(contract) : Container.GetExportedValues<T>();
        }
    }

Feb 13, 2012 at 6:44 AM

Make all the reference Dll files (Copy Local) to false.