/// <summary> /// Lists assembly load errors and attempts to construct instances of all Types declared as Exports (which are ICheckable) /// </summary> /// <param name="notifier"></param> public void Check(ICheckNotifier notifier) { foreach (KeyValuePair <string, Exception> badAssembly in _mefPlugins.ListBadAssemblies()) { notifier.OnCheckPerformed(new CheckEventArgs("Could not load assembly " + badAssembly.Key, CheckResult.Fail, badAssembly.Value)); } foreach (Type t in _mefPlugins.GetAllTypes()) { notifier.OnCheckPerformed(new CheckEventArgs("Found Type " + t, CheckResult.Success, null)); if (typeof(ICheckable).IsAssignableFrom(t)) { try { _mefPlugins.CreateA <ICheckable>(t.FullName); } catch (Exception ex) { notifier.OnCheckPerformed(new CheckEventArgs( "Class " + t.FullName + " implements ICheckable but could not be created as an ICheckable.", CheckResult.Warning, ex)); } } } }
/// <summary> /// Looks for the class name within the defined Types in all assemblies loaded in MEF. If you pass an ICheckNotifier which responds to ProposedFixes and the class /// is found under a different namespace (e.g. due to the coder of the plugin refactoring the class to a new location in his assembly) then the callback /// userAcceptedSubstitution will be invoked. Use AcceptAllCheckNotifier if you want the callback to always be called. /// </summary> /// <param name="notifier"></param> public void Check(ICheckNotifier notifier) { if (string.IsNullOrWhiteSpace(_classToFind)) { notifier.OnCheckPerformed(new CheckEventArgs( "MEFChecker was asked to check for the existence of an Export class but the _classToFind string was empty", CheckResult.Fail, null)); return; } string typeNameOnly = _classToFind.Substring(_classToFind.LastIndexOf(".") + 1); var allTypes = _mefPlugins.GetAllTypes().ToArray(); if (allTypes.Any(t => t.FullName.Equals(_classToFind))) { notifier.OnCheckPerformed(new CheckEventArgs( "Found MEF class " + _classToFind + "", CheckResult.Success, null)); } else { Type[] substitute = allTypes.Where(t => t.Name.Equals(typeNameOnly)).ToArray(); if (substitute.Length == 0) { notifier.OnCheckPerformed(new CheckEventArgs( "Could not find MEF class called " + _classToFind + " in LoadModuleAssembly.GetAllTypes() and couldn't even find any with the same basic name (Note that we only checked Exported MEF types e.g. classes implementing IPluginAttacher, IPluginDataProvider etc)", CheckResult.Fail, null)); Dictionary <string, Exception> badAssemblies = _mefPlugins.ListBadAssemblies(); if (badAssemblies.Any()) { notifier.OnCheckPerformed(new CheckEventArgs( "It is possible that the class you are looking for is in the BadAssemblies list", CheckResult.Fail, null)); } foreach (KeyValuePair <string, Exception> badAssembly in badAssemblies) { notifier.OnCheckPerformed(new CheckEventArgs("Bad Assembly " + badAssembly.Key, CheckResult.Warning, badAssembly.Value)); } } else if (substitute.Length == 1) { bool acceptSubstitution = notifier.OnCheckPerformed(new CheckEventArgs( "Could not find MEF class called " + _classToFind + " but did find one called " + substitute[0].FullName, CheckResult.Fail, null, "Change reference to " + _classToFind + " to point to MEF assembly type " + substitute[0].FullName)); if (acceptSubstitution) { _userAcceptedSubstitution(substitute[0].FullName); } } else { notifier.OnCheckPerformed(new CheckEventArgs( "Could not find MEF class called " + _classToFind + ", we were looking for a suitable replacment (a Type with the same basic name) but we found " + substitute.Length + " subistutitions!!! (" + substitute.Aggregate("", (s, n) => s + n.FullName + ","), CheckResult.Fail, null)); } } }