diff options
Diffstat (limited to 'MediaBrowser.Common')
| -rw-r--r-- | MediaBrowser.Common/Kernel/BaseKernel.cs | 15 | ||||
| -rw-r--r-- | MediaBrowser.Common/MediaBrowser.Common.csproj | 1 | ||||
| -rw-r--r-- | MediaBrowser.Common/Mef/MefUtils.cs | 43 | ||||
| -rw-r--r-- | MediaBrowser.Common/Plugins/BasePlugin.cs | 3 | ||||
| -rw-r--r-- | MediaBrowser.Common/Plugins/BaseTheme.cs | 66 |
5 files changed, 122 insertions, 6 deletions
diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index 5a0e1c5e5..a6081a688 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Events;
using MediaBrowser.Common.Logging;
+using MediaBrowser.Common.Mef;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Net.Handlers;
using MediaBrowser.Common.Plugins;
@@ -10,6 +11,7 @@ using System; using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
+using System.ComponentModel.Composition.Primitives;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -88,6 +90,9 @@ namespace MediaBrowser.Common.Kernel /// </summary>
private IDisposable HttpListener { get; set; }
+ /// <summary>
+ /// Gets the MEF CompositionContainer
+ /// </summary>
private CompositionContainer CompositionContainer { get; set; }
protected virtual string HttpServerUrlPrefix
@@ -184,18 +189,20 @@ namespace MediaBrowser.Common.Kernel // This will prevent the .dll file from getting locked, and allow us to replace it when needed
IEnumerable<Assembly> pluginAssemblies = Directory.GetFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly).Select(f => Assembly.Load(File.ReadAllBytes((f))));
- var catalog = new AggregateCatalog(pluginAssemblies.Select(a => new AssemblyCatalog(a)));
+ var catalogs = new List<ComposablePartCatalog>();
+
+ catalogs.AddRange(pluginAssemblies.Select(a => new AssemblyCatalog(a)));
// Include composable parts in the Common assembly
- catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
+ catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
if (includeCurrentAssembly)
{
// Include composable parts in the subclass assembly
- catalog.Catalogs.Add(new AssemblyCatalog(GetType().Assembly));
+ catalogs.Add(new AssemblyCatalog(GetType().Assembly));
}
- return new CompositionContainer(catalog);
+ return MefUtils.GetSafeCompositionContainer(catalogs);
}
/// <summary>
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index baa846e48..c08716614 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -87,6 +87,7 @@ <Compile Include="Logging\BaseLogger.cs" />
<Compile Include="Logging\LogSeverity.cs" />
<Compile Include="Logging\TraceFileLogger.cs" />
+ <Compile Include="Mef\MefUtils.cs" />
<Compile Include="Net\Handlers\StaticFileHandler.cs" />
<Compile Include="Net\MimeTypes.cs" />
<Compile Include="Plugins\BaseTheme.cs" />
diff --git a/MediaBrowser.Common/Mef/MefUtils.cs b/MediaBrowser.Common/Mef/MefUtils.cs new file mode 100644 index 000000000..55d888697 --- /dev/null +++ b/MediaBrowser.Common/Mef/MefUtils.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic;
+using System.ComponentModel.Composition.Hosting;
+using System.ComponentModel.Composition.Primitives;
+using System.Linq;
+using System.Reflection;
+
+namespace MediaBrowser.Common.Mef
+{
+ public static class MefUtils
+ {
+ /// <summary>
+ /// Plugins that live on both the server and UI are going to have references to assemblies from both sides.
+ /// But looks for Parts on one side, it will throw an exception when it seems Types from the other side that it doesn't have a reference to.
+ /// For example, a plugin provides a Resolver. When MEF runs in the UI, it will throw an exception when it sees the resolver because there won't be a reference to the base class.
+ /// This method will catch those exceptions while retining the list of Types that MEF is able to resolve.
+ /// </summary>
+ public static CompositionContainer GetSafeCompositionContainer(IEnumerable<ComposablePartCatalog> catalogs)
+ {
+ var newList = new List<ComposablePartCatalog>();
+
+ // Go through each Catalog
+ foreach (var catalog in catalogs)
+ {
+ try
+ {
+ // Try to have MEF find Parts
+ catalog.Parts.ToArray();
+
+ // If it succeeds we can use the entire catalog
+ newList.Add(catalog);
+ }
+ catch (ReflectionTypeLoadException ex)
+ {
+ // If it fails we can still get a list of the Types it was able to resolve and create TypeCatalogs
+ var typeCatalogs = ex.Types.Where(t => t != null).Select(t => new TypeCatalog(t));
+ newList.AddRange(typeCatalogs);
+ }
+ }
+
+ return new CompositionContainer(new AggregateCatalog(newList));
+ }
+ }
+}
diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs index a764c5eab..70e573817 100644 --- a/MediaBrowser.Common/Plugins/BasePlugin.cs +++ b/MediaBrowser.Common/Plugins/BasePlugin.cs @@ -4,6 +4,7 @@ using MediaBrowser.Common.Serialization; using MediaBrowser.Model.Plugins;
using System;
using System.IO;
+using System.Reflection;
namespace MediaBrowser.Common.Plugins
{
@@ -12,7 +13,7 @@ namespace MediaBrowser.Common.Plugins /// </summary>
public abstract class BasePlugin : IDisposable
{
- private IKernel Kernel { get; set; }
+ protected IKernel Kernel { get; private set; }
/// <summary>
/// Gets or sets the plugin's current context
diff --git a/MediaBrowser.Common/Plugins/BaseTheme.cs b/MediaBrowser.Common/Plugins/BaseTheme.cs index f06825262..32a28258b 100644 --- a/MediaBrowser.Common/Plugins/BaseTheme.cs +++ b/MediaBrowser.Common/Plugins/BaseTheme.cs @@ -1,4 +1,12 @@ -
+using MediaBrowser.Common.Mef;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.ComponentModel.Composition.Hosting;
+using System.ComponentModel.Composition.Primitives;
+using System.Windows;
+using System.Windows.Controls;
+
namespace MediaBrowser.Common.Plugins
{
public abstract class BaseTheme : BasePlugin
@@ -10,5 +18,61 @@ namespace MediaBrowser.Common.Plugins return true;
}
}
+
+ /// <summary>
+ /// Gets the MEF CompositionContainer
+ /// </summary>
+ private CompositionContainer CompositionContainer { get; set; }
+
+ /// <summary>
+ /// Gets the list of global resources
+ /// </summary>
+ [ImportMany(typeof(ResourceDictionary))]
+ public IEnumerable<ResourceDictionary> GlobalResources { get; private set; }
+
+ /// <summary>
+ /// Gets the list of pages
+ /// </summary>
+ [ImportMany(typeof(Page))]
+ public IEnumerable<Page> Pages { get; private set; }
+
+ /// <summary>
+ /// Gets the pack Uri of the Login page
+ /// </summary>
+ public abstract Uri LoginPageUri { get; }
+
+ protected override void InitializeInUi()
+ {
+ base.InitializeInUi();
+
+ ComposeParts();
+ }
+
+ private void ComposeParts()
+ {
+ var catalog = new AssemblyCatalog(GetType().Assembly);
+
+ CompositionContainer = MefUtils.GetSafeCompositionContainer(new ComposablePartCatalog[] { catalog });
+
+ CompositionContainer.ComposeParts(this);
+
+ CompositionContainer.Catalog.Dispose();
+ }
+
+ protected override void DisposeInUi()
+ {
+ base.DisposeInUi();
+
+ CompositionContainer.Dispose();
+ }
+
+ protected Uri GeneratePackUri(string relativePath)
+ {
+ string assemblyName = GetType().Assembly.GetName().Name;
+
+ string uri = string.Format("pack://application:,,,/{0};component/{1}", assemblyName, relativePath);
+
+ return new Uri(uri, UriKind.Absolute);
+ }
}
}
|
