CompositionInitializer
class (the System.ComponentModel.CompositionInitialization.dll library), which allows you to create a composition for a specific object, initializing all imports of this object and other dependent entities. This functionality is especially important for Silverlight applications, where the decentralization of the component elements of an application is particularly pronounced.SatisfyImports()
method of this class creates a global container that will be used in all further calls to SatisfyImports()
. SatisfyImports
produces a composition of all objects that are found in the current assembly and all dependent assemblies (that is, within the entire XAP file). Objects instantiated during composition will be in the container until the latter is destroyed, i.e. until the end of the program.SatisfyImports()
method cannot have the [Export]
attribute;public partial class Shell : UserControl<br>{<br> public MainPage()<br> {<br> ComposeContainer()<br> }<br><br> private void ComposeContainer()<br> {<br> CompositionInitializer.SatisfyImports( this );<br> }<br>} <br><br> * This source code was highlighted with Source Code Highlighter .
DeploymentCatalog
:CompositionHost
class must be used (see below).DeploymentCatalog
will try to add them all to the catalog, which can lead to an exception (exception) if recomposition is not allowed. You should set CopyLocal=False
to duplicate assemblies of the entire application or use my extension for VS2010 XapsMinifierprivate void CancelLoading()<br>{<br> catalog.CancelAsync();<br>}<br><br> private void LoadXapFile( string xapPath)<br>{<br> DeploymentCatalog catalog = new DeploymentCatalog(xapPath);<br> catalog.DownloadCompleted += new EventHandler<AsyncCompletedEventArgs>(DownloadCompleted);<br> catalog.DownloadProgressChanged += new EventHandler<DownloadProgressChangedEventArgs>(ProgressChanged);<br> catalog.DownloadAsync();<br> _aggregateCatalog.Catalogs.Add(catalog);<br>}<br><br> void DownloadCompleted( object sender, System.ComponentModel.AsyncCompletedEventArgs e)<br>{<br> if (e.Error != null )<br> throw e.Error;<br>}<br><br> void catalog_DownloadProgressChanged( object sender, DownloadProgressChangedEventArgs e)<br>{<br> int progress = e.ProgressPercentage;<br> long received = e.BytesReceived;<br> long total = e.TotalBytesToReceive;<br>} <br><br> * This source code was highlighted with Source Code Highlighter .
public partial class Shell : UserControl<br>{<br> public MainPage()<br> {<br> ComposeContainer()<br> }<br><br> private void ComposeContainer()<br> {<br> _aggregateCatalog = new AggregateCatalog( new DeploymentCatalog());<br> CompositionHost.Initialize(_aggregateCatalog);<br> CompositionInitializer.SatisfyImports( this );<br> }<br>} <br><br> * This source code was highlighted with Source Code Highlighter .
[Export]<br> public class DocumentViewModel {<br><br> [Import] <br> public ExportFactory<IDocument> DocumentFactory<br> {<br> get ;<br> set ;<br> }<br><br> protected List <IDocument> Documents<br> {<br> get ;<br> set ;<br> }<br><br> public void CreateDocument() <br> {<br> Documents.Add(DocumentFactory.CreateExport().Value);<br> }<br>} <br><br> * This source code was highlighted with Source Code Highlighter .
Creating parts of the composition using ExportFactory <T>, the developer takes full responsibility for the lifetime of the created instance. If instances require freeing memory, then you can use the standard Dispose()
pattern.[Export]<br> public class DocumentViewModel : IDisposable <br>{<br> private bool isDisposed = false ;<br> [Import] <br> public ExportFactory<IDocument> DocumentFactory<br> {<br> get ;<br> set ;<br> }<br><br> private List <ExportLifetimeContext<IDocument>> ExportLifeTimeContextList<br> {<br> get ;<br> set ;<br> }<br><br> protected List <IDocument> Documents<br> {<br> get ;<br> set ;<br> }<br><br> public void CreateDocument() <br> {<br> ExportLifetimeContext<IDocument> LifeTimeContext = DocumentFactory.CreateExport();<br> ExportListLifeTimeContext.Add(LifeTimeContext);<br> Documents.Add(LifeTimeContext.Value);<br> }<br><br> public void Dispose()<br> {<br> Dispose( true );<br> GC.SuppressFinalize( this );<br> }<br><br> public void Dispose( bool disposing)<br> {<br> if (isDisposed)<br> return ;<br><br> if (disposing)<br> {<br> foreach (IDisposable d in ExportLifeTimeContextList)<br> d.Dispose();<br> }<br> <br> isDisposed = true ;<br> }<br>} <br><br> * This source code was highlighted with Source Code Highlighter .
IThemeLoader
interface is IThemeLoader
. This class is able to extract the required resources and contains the name of the topic.[InheritedExport]<br> public interface IThemeLoader<br>{<br> string Name<br> {<br> get ;<br> }<br><br> IEnumerable <ResourceDictionary> Resources<br> {<br> get ;<br> }<br><br>}<br><br><br> public class ThemeLoader : ThemeLoaderBase<br>{<br><br> #region IThemeLoader Members<br><br> public override string Name<br> {<br> get <br> {<br> return "Accent" ;<br> }<br> }<br><br> public override IEnumerable <ResourceDictionary> Resources<br> {<br> get <br> {<br> yield return LoadResourceDictionary( "/SLandMEFdevcamp.AccentTheme;component/Style.xaml" );<br> }<br> }<br><br> #endregion <br> <br> /* <br> protected virtual ResourceDictionary LoadResourceDictionary(string uri) <br> { <br> return new ResourceDictionary <br> { <br> Source = new Uri(uri, UriKind.Relative) <br> }; <br> } <br> */ <br>}<br> <br> * This source code was highlighted with Source Code Highlighter .
The attribute InheritedExport
indicates that all implementations of the interface marked with this attribute should be exported.DeploymentCabinet
, which initiates a recomposition.IThemeLoader
will be IThemeLoader
and a new list of available themes will be displayed on the UI.private AggregateCatalog _aggregateCatalog = null ;<br> private IEnumerable <IThemeLoader> themesLoaders;<br><br> private void ComposeContainer()<br>{<br> _aggregateCatalog = new AggregateCatalog( new DeploymentCatalog());<br> CompositionHost.Initialize(_aggregateCatalog);<br> CompositionInitializer.SatisfyImports( this );<br>}<br><br>[ImportMany(AllowRecomposition = true )]<br> public IEnumerable <IThemeLoader> ThemesLoaders<br>{<br> get <br> {<br> return themesLoaders;<br> }<br> set <br> {<br> themesLoaders = value ;<br> RaisePropertyChanged( "ThemesLoaders" );<br> }<br>}<br><br> private IThemeLoader theme;<br> public IThemeLoader Theme<br>{<br> get <br> {<br> return theme;<br> }<br> set <br> {<br> theme = value ;<br> LoadTheme( value );<br> RaisePropertyChanged( "Theme" );<br> }<br>}<br><br> private void LoadTheme(IThemeLoader themeLoader)<br>{<br> if (themeLoader.Resources == null || !themeLoader.Resources.Any())<br> return ;<br><br> App.Current.Resources.MergedDictionaries.Clear();<br><br> foreach ( var resourceDict in themeLoader.Resources)<br> App.Current.Resources.MergedDictionaries.Add(resourceDict);<br>}<br><br> private void Button_Click( object sender, System.Windows.RoutedEventArgs e)<br>{<br> DeploymentCatalog catalog = new DeploymentCatalog(XapUrlTextBox.Text);<br> catalog.DownloadAsync();<br><br> _aggregateCatalog.Catalogs.Add(catalog);<br>} <br><br> * This source code was highlighted with Source Code Highlighter .
In this case, XAP files with themes are located in the same folder as the main XAP file, and therefore you can specify only the name of the XAP file without a full url. For example, SLandMEFdevcamp.AccentTheme.xap, SLandMEFdevcamp.Win7Theme.xap.ComposeContainer()
)XapUrlTextBox
field and presses the download button. Loading the XAP file results in adding a new implementation of IThemeLoader
to the directory and recommending the ThemesLoaders property, which is associated with the ListBox
element on the formListBox
element, a change in the Theme property is generated, which causes the LoadTheme()
method to be LoadTheme()
LoadTheme()
method removes all existing resources and adds resources for the topic the user has selected.ExportFactory<T>
class has ExportFactory<T>
added to the desktop version of the library in MEF 2 Preview 2 .Source: https://habr.com/ru/post/106486/
All Articles