SmartDll.dll

Iniciado por Keyen Night, 21 Julio 2010, 19:19 PM

0 Miembros y 1 Visitante están viendo este tema.

Keyen Night

Buenas tardes/días/noches a todos xD me ha llamado mucho la atención lo de los plugings y addons que se puede hacer con System.Reflection en .Net así que he me puse a hacer una dll SmartDll.dll que sirviera para facilitar la comunicación entre el programa y los plugins de una manera más comoda, entonces vengo aqui a pedir consejos y opiniones mientras voy desarrollando el proyecto de tal manera que quede lo mejor posible, aqui está el source:

Para que no tengan que leerselo y analizarlo basicamente crea un objeto apartir de la dll a cargar comprobando que dentro de ella exista la clase Plugin
dentro de esta clase debe ir todo el contenido y además debe ser la clase principal y tambien el nombre de raiz y el del ensamblado del plugins deben ser los mismos, luego tenemos 2 funciones una que devuelve todos los controles dentro del plugin y otra que te devuelve solo los de un tipo en especifico por ejemplo solo los TextBox

Código (vbnet) [Seleccionar]
Public Class Dll

#Region " Private "

    Private _
    _DllInfo As FileInfo, _
    _EntryPoint As String, _
    _Assembly As Assembly, _
    _ObjectType As Type, _
    _ObjectInstance As Object

#End Region

#Region " Private Shared "



#End Region

#Region " Public "

    Public Sub New(ByVal Path As String)
        Try
            If IsSmartDll(Path) Then
                _DllInfo = New FileInfo(Path)
                _EntryPoint = New FileInfo(Path).Name.Split(CChar("."))(0) & "."
                _Assembly = Assembly.LoadFile(Path)
                _ObjectType = _Assembly.GetType(_EntryPoint & "Plugin")
                _ObjectInstance = _Assembly.CreateInstance(_EntryPoint & "Plugin")
            Else
                Throw New Exception(Path & " not belongs to SmartDll")
            End If
        Catch ex As Exception
            Throw New Exception(ex.Message, ex.InnerException)
        End Try
    End Sub

    Public ReadOnly Property FileInfo() As [FileInfo]
        Get
            Return _DllInfo
        End Get
    End Property

    Public Function GetControlsByType(ByVal FindType As Type) As List(Of Control)
        GetControlsByType = New List(Of Control)

        For Each Objeto As PropertyInfo In _ObjectType.GetProperties

            Try

                If Objeto.PropertyType.Name = FindType.Name Then
                    GetControlsByType.Add(CType(Objeto.GetValue(_ObjectInstance, New Object() {}), Control))
                Else
                    Continue For
                End If

            Catch
                Continue For
            End Try

        Next

    End Function

    Public Function GetControls() As List(Of Control)
        GetControls = New List(Of Control)

        For Each Objeto As PropertyInfo In _ObjectType.GetProperties

            Try
                GetControls.Add(CType(Objeto.GetValue(_ObjectInstance, New Object() {}), Control))
            Catch
                Continue For
            End Try

        Next

    End Function

#End Region

#Region " Public Shared "

    Public Shared Function IsSmartDll(ByVal Path) As Boolean
        Try
            Dim Dll As Assembly = Assembly.LoadFile(Path)

            Return Dll.GetType(New FileInfo(Path).Name.Split(CChar("."))(0) & ".Plugin") IsNot Nothing

        Catch
            Return False
        End Try
    End Function

#End Region

End Class


Pueden decir que creen ustedes que hace falta, dudas, criticas o correcciones de errorres o recomendaciones de mejores practicas ;D

Notas:

  • Para que serviria llamar Subs y Funciones de un plugin?
La Fé Mueve Montañas...
                                    ...De Dinero

La programación es más que un trabajo es más que un hobby es una pasión...

[D4N93R]

Muy bien! pero (ups) yo creo que es mejor que crees un SDK para los plugines, más que un comprobador de manera de saber si está bien "redactado" el dll del plugin.

Me explico, Supongamos que tengo un programa (windows form) entonces quiero que se le añadan plugines, pero los plugines no solo son visuales, pueden ser muchas cosas más, por ejemplo cargar otra ventana o cierto comportamiento diferente.

Entonces tienes que proveer un sdk, que creo yo, debe consistir en una Interfaz. Sigamos con el ejemplo:

La interfaz:
Código (csharp) [Seleccionar]

public class AplicationManager
{
    // codigo principal de la aplicacion
    public static AplicationManager Current { get; }
}

public interface IPlugin
{
      void Init(AplicationManager appManager);
      void OnExit();
      public string Name {get; }
}


Entonces, AplicationManager es donde se maneja todo el comportamiento principal de la aplicación, y todo plugin debe implementar de IPlugin, así de esa manera:

Código (csharp) [Seleccionar]


public class MySuperPlugin : IPlugin
{
      private AplicationManager m_appMgr =  null;
      void Init(AplicationManager appManager)
      {
          m_appMgr = appManager;
          System.Timers.Timer aTimer = new System.Timers.Timer(10000);
          aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
          aTimer.Interval = 2000;
          aTimer.Enabled = true;
      }

      private static void OnTimedEvent(object source, ElapsedEventArgs e)
      {
          m_appMgr.Current.SomeMethod();
      }

      public void OnExit()
      {
           //supuestamente esto es un evento que se ejecuta cuando se está cerrando
           //lla aplicacion, como? pues AplicationManager tiene la lista de plugines
           //cargados, y los cierra uno por uno antes de salir
           appManager.Current.XXXXX.XXX = "TEST";
            // con esto quiero decir que tenemos acceso a la
           //aplicación principal  en cualquier momento:)
      }

      public string Name {get { return "My Super Plugin!!! v1.0"; } }
}



Si no me expliqué bien, me dices y edito el post xD hehe saludos!

Keyen Night

Si ya te entiendo tambien pense en eso pero me dio flogera xD obviamente se necesita que el plugin pueda tener acceso al programa que lo cargo, bueno seguiré trabajando y cualquier avance lo comunico, Gracias por tu respuesta ;)
La Fé Mueve Montañas...
                                    ...De Dinero

La programación es más que un trabajo es más que un hobby es una pasión...

[D4N93R]

Excelente, y tranquilo que parece más difícil pero no lo es, tener un ApplicationManager o el nombre que le pongas es muy importante y te ayuda mucho en el desarrollo de aplicaciones grandes. Un dato:

Código (csharp) [Seleccionar]


public class AplicationManager
{
    private static AplicationManager m_appMgr = null;
    public static AplicationManager Current
    {
        get
        {
             if(m_appMgr == null)
                m_appMgr = new AplicationManager();
             return m_appMgr;
        }
     }

    // despues todo el codigo principal de la aplicacion
}



Con esto tienes :)

raul338

Cita de: Keyen Night en 21 Julio 2010, 19:19 PM
Notas:

  • Para que serviria llamar Subs y Funciones de un plugin?

Serviria para darle uso al plugin, a mi se me habia ocurrido en su momento que devolviera una lista con las funciones (un menu para agregarlo al StripMenu) y de ahi que el usuario los llame cuando quiera :P

Keyen Night

Si, me llamo la atención fue ese tema donde tu y otro usuario respondian a otro que preguntaba como hacer un sistema de plugins.

D4N93R ahora que voy a la práctica me he enredado todo, las Interface si son realmente la mejor forma de crear un sistema de plugins, ya que he googleado y bueno es la alternativa que ofrecen todos, lo que no entiendo es como esto hace posible que me comunique con la aplicacion que cargo el plugin y tengo otra duda tengo que tener la interface en la aplicacion que carga los plugins y tambien en los plugin pero si cada uno es diferente (cada plugin) como la interface de la aplicacion princiapal tendra el mismo contenido que los plugins?

Quisas estoy todo confundido xD
La Fé Mueve Montañas...
                                    ...De Dinero

La programación es más que un trabajo es más que un hobby es una pasión...

[D4N93R]

Si bueno, una vez que lo comprendas no es nada difícil :D

Usando el código anterior, supongamos que mi aplicación es un notepad, normal igualito que el de windows.

entonces, en vez de programar el comportamiento en Form1.cs xD lo programas todo en AplicationManager, un pequeño ejemplo:

Nota: Código sin Visual Studio.
Código (csharp) [Seleccionar]

public class Form1: Form
{

  void Guardar_Click(object sender, EventHandler e)
  {
      //este es el método que maneja el evento click del botón guardar del formulario.
      // En vez de hacer todo el código para guardar acá, haces:
      AplicationManager.SaveDocument(textbox1.Text);
      //ves? de esta manera todo el comportamiento de la aplicación ya no se hace en el form1 :D
  }

}


Ahora un sistema de plugins en el mismo código. Un plugin que saque un botón y muestre un formulario para ver las actualizaciones disponibles, y que también al cargar revise si hay actualizaciones
Código (csharp) [Seleccionar]

//para esto necesitamos que nuestro AplicationManager tenga acceso a todo, por eso:
//otra cosa! los plugines están en AplicationManager, en una Lista, algo así List<IPlugin>
// Y siempre son cargados antes de iniciar el formulario, esto lo haces en el Program.cs
public class Form1: Form
{

  void Form_Load(object sender, EventHandler e)
  {
      AplicationManager.Current.MainForm = this;

     // Obviamente en el AplicationManager tiene que haber una propiedad de tipo Form que se llame MainForm :D


  }
  void Guardar_Click(object sender, EventHandler e)
  {
      AplicationManager.Current.SaveDocument(textbox1.Text);
  }

}


Es muy importate que tengas eventos y métodos por todo el AplicationManager, de esta forma puedes hacer más cosas con los plugines.

Ahora el código de los plugines:

Código (csharp) [Seleccionar]

public class UpdatePlugin : IPlugin
{
  AplicationManager m_appMgr;
  public void Update()
  {
     //Código para actualizar la aplicación
  }
  void Init(AplicationManager appManager)
  {
      m_appMgr = appManager;
      Update(); //Este método se llama cuando se inicia la apliación porque al cargar los plugines se les debe llamar a éste método, o si quieres lo ahces en el constructor.

     //ahora agarramos el form de AplicationManager y buscamos el Menu donde queremos meter el control y listo:
     AplicationManager.Current.MainForm.FindControl(..... // ahí te lo dejo, tengo sueño ya hehehe
     //también puedes crear un método para agregar botones a un menu en específico, eso lo pondrías en el Application manager.. pero bueno es cuestión de programar y añadir detalles..
  }
  void OnExit()
  {  }
  public string Name {get { return "Updates Plugin" } }
 
}