via slideshare sistema resumen que lectinas las funciones complemento clasica c3b alterna c# plugins extensibility

slideshare - Escribir el sistema de complemento C#



via clasica del complemento (3)

Managed Extensibility Framework (MEF) es una nueva biblioteca en .NET que permite una mayor reutilización de aplicaciones y componentes. Usando MEF, las aplicaciones .NET pueden hacer que el cambio sea compilado estáticamente a compuesto dinámicamente. Si está creando aplicaciones extensibles, marcos extensibles y extensiones de aplicaciones, entonces MEF es para usted.

http://www.codeplex.com/MEF

Editar: CodePlex se va: el código se ha movido a Github solo para fines de archivo: https://github.com/MicrosoftArchive/mef

Intento escribir un sistema de complemento para proporcionar algo de extensibilidad a una aplicación mía para que alguien pueda escribir un complemento para la aplicación sin tocar el código de la aplicación principal (y arriesgarse a romper algo).

Tengo la interfaz base "IPlugin" escrita (atm, nada está implementado)

Así es como estoy cargando:

public static void Load() { // rawr: http://www.codeproject.com/KB/cs/c__plugin_architecture.aspx String[] pluginFiles = Directory.GetFiles(Plugins.PluginsDirectory, "*.dll"); foreach (var plugin in pluginFiles) { Type objType = null; try { //Assembly.GetExecutingAssembly().GetName().Name MessageBox.Show(Directory.GetCurrentDirectory()); Assembly asm = Assembly.Load(plugin); if (asm != null) { objType = asm.GetType(asm.FullName); if (objType != null) { if (typeof(IPlugin).IsAssignableFrom(objType)) { MessageBox.Show(Directory.GetCurrentDirectory()); IPlugin ipi = (IPlugin)Activator.CreateInstance(objType); ipi.Host = Plugins.m_PluginsHost; ipi.Assembly = asm; } } } } catch (Exception e) { MessageBox.Show(e.ToString(), "Unhandled Exception! (Please Report!)", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information); } } }

Un amigo trató de ayudar, pero realmente no entendí lo que estaba mal.

La estructura de carpetas para complementos es la siguiente:

/
/ Plugins /

Todos los complementos hacen referencia a un .dll llamado "Lab.Core.dll" en el directorio [raíz] y no está presente en el directorio de complementos debido a la carga de referencias duplicadas.

El sistema de complementos se carga desde Lab.Core.dll, al que también hace referencia mi ejecutable. Escriba "IPlugin" también en Lab.Core.dll. Lab.Core.dll es, exactamente como el nombre, el núcleo de mi aplicación.

EDITAR:

Pregunta: ¿Por qué / Qué es esa excepción que recibo y cómo podría solucionarlo?

EDICION FINAL:

Ok, así que decidí volver a escribirlo después de mirar algún código fuente que un amigo escribió para un regulador TF2.

Esto es lo que obtuve y funciona:

public class TestPlugin : IPlugin { #region Constructor public TestPlugin() { // } #endregion #region IPlugin Members public String Name { get { return "Test Plugin"; } } public String Version { get { return "1.0.0"; } } public String Author { get { return "Zack"; } } public Boolean OnLoad() { MessageBox.Show("Loaded!"); return true; } public Boolean OnAllLoaded() { MessageBox.Show("All loaded!"); return true; } #endregion } public static void Load(String file) { if (!File.Exists(file) || !file.EndsWith(".dll", true, null)) return; Assembly asm = null; try { asm = Assembly.LoadFile(file); } catch (Exception) { // unable to load return; } Type pluginInfo = null; try { Type[] types = asm.GetTypes(); Assembly core = AppDomain.CurrentDomain.GetAssemblies().Single(x => x.GetName().Name.Equals("Lab.Core")); Type type = core.GetType("Lab.Core.IPlugin"); foreach (var t in types) if (type.IsAssignableFrom((Type)t)) { pluginInfo = t; break; } if (pluginInfo != null) { Object o = Activator.CreateInstance(pluginInfo); IPlugin plugin = (IPlugin)o; Plugins.Register(plugin); } } catch (Exception) { } } public static void LoadAll() { String[] files = Directory.GetFiles("./Plugins/", "*.dll"); foreach (var s in files) Load(Path.Combine(Environment.CurrentDirectory, s)); for (Int32 i = 0; i < Plugins.List.Count; ++i) { IPlugin p = Plugins.List.ElementAt(i); try { if (!p.OnAllLoaded()) { Plugins.List.RemoveAt(i); --i; } } catch (Exception) { Plugins.List.RemoveAt(i); --i; } } }


Como respuesta lateral, uso estas 2 interfaces para implementar eso

///<summary> ///</summary> public interface IPlugin { ///<summary> ///</summary> string Name { get; } ///<summary> ///</summary> string Description { get; } ///<summary> ///</summary> string Author { get; } ///<summary> ///</summary> string Version { get; } ///<summary> ///</summary> IPluginHost Host { get; set; } ///<summary> ///</summary> void Init(); ///<summary> ///</summary> void Unload(); ///<summary> ///</summary> ///<returns></returns> IDictionary<int, string> GetOptions(); ///<summary> ///</summary> ///<param name="opcion"></param> void ExecuteOption(int option); } ///<summary> ///</summary> public interface IPluginHost { ///<summary> ///</summary> IDictionary<string, object> Variables { get; } ///<summary> ///</summary> ///<param name="plugin"></param> void Register(IPlugin plugin); }


Parece que tienes una referencia circular. Dijo que sus complementos hacen referencia a Lab.Core.DLL, pero también dice que los complementos se cargan desde Lab.Core.DLL.

¿Estoy entendiendo mal lo que está sucediendo aquí?

EDITAR: OK ahora que ha agregado su pregunta a la pregunta ...

Necesitas tener Lab.Core.DLL accesible para el plugin que se está cargando ya que es una dependencia. Normalmente eso significaría tenerlo en el mismo directorio o en el GAC.

Sospecho que hay problemas de diseño más profundos en juego aquí, pero este es su problema inmediato.