Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Moderatore di Windows e software L'avatar di URANIO
    Registrato dal
    Dec 1999
    residenza
    Casalpusterlengo (LO)
    Messaggi
    1,290

    Eventi e chiamate a DLL senza riferimenti (+ILGenerator)

    Mi spiego meglio.

    Devo interfacciami ad un prodotto che ha le sue API per comandarlo.
    Tutto funziona SE NON FOSSE CHE, aggiornando la versione del prodotto bisogna aggiornare anche le DLL o non funziona.

    Abbiamo pensato quindi di rendere il programma indipendente dalla versione delle DLL e di richiamarle via System.Reflection.Assembly.
    Tutto funziona, riesco a chiamare funzioni e leggere property, SE NON FOSSE CHE ho bisogno di gestire anche degli eventi scatenati dalla DLL, e qua c'è il problema... Non riesco a farlo.

    Qualcuno ha mai dovuto interfacciarsi ad una dll senza usare riferimenti alla stessa?

    Ho trovato questa pagina
    https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx
    Ma non mi è chiaro il funzionamento di ILGenerator.

  2. #2
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,539
    Quote Originariamente inviata da URANIO Visualizza il messaggio
    Mi spiego meglio.

    Devo interfacciami ad un prodotto che ha le sue API per comandarlo.
    Tutto funziona SE NON FOSSE CHE, aggiornando la versione del prodotto bisogna aggiornare anche le DLL o non funziona.

    Abbiamo pensato quindi di rendere il programma indipendente dalla versione delle DLL e di richiamarle via System.Reflection.Assembly.
    Tutto funziona, riesco a chiamare funzioni e leggere property, SE NON FOSSE CHE ho bisogno di gestire anche degli eventi scatenati dalla DLL, e qua c'è il problema... Non riesco a farlo.

    Qualcuno ha mai dovuto interfacciarsi ad una dll senza usare riferimenti alla stessa?

    Ho trovato questa pagina
    https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx
    Ma non mi è chiaro il funzionamento di ILGenerator.
    Ciao "cugino"
    ok, non so dove ti fermi, ma ti posto un esempio funzionante, da li poi vediamo cosa non riesci a gestire nel tuo codice:

    DLL da importare (stessa cartella del exe):
    codice:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Timers;
    
    
    namespace ClassLibrary1
    {
        public delegate void MyDelegate(object sender, EventArgs e);
        
        public class Class1
        {
            Timer timer;
            MyDelegate myDel = null;
    
    
            public Class1()
            {
                timer = new Timer(1000);
                timer.Elapsed += (obj,arg) => OnTick(arg);
                timer.Start();
            }
    
    
            protected void OnTick(EventArgs e)
            {
                if (this.myDel != null)
                    this.myDel(this, e);
            }
    
    
            public event MyDelegate Tick
            {
                add { this.myDel += value; }
                remove { this.myDel -= value; }
            }
        }    
    }
    Una semplice dll che espone un evento chiamato da un timer e un delegato apposito, ma con argomenti di tipo conosciuto (nel caso siano sconosciuti a priori anche questi, nel tick della classe target usa i dynamic al posto dei tipi conosciuti).

    classe target:
    codice:
    using System;using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            const string libraryName = "ClassLibrary1.dll";
            const string typeName = "ClassLibrary1.Class1";
            const string eventName = "Tick";
            const string delegateTypeName = "ClassLibrary1.MyDelegate";
            const string methodName = "OnTick";
    
    
            public Form1()
            {
                InitializeComponent();
                //carico l'assembly (dll) 
                Assembly sourceAsm = Assembly.LoadFrom(libraryName);
                //recupero il tipo che contiene l'evento (dll) 
                Type sourceType = sourceAsm.GetType(typeName);
                //recupero il tipo del delegato (dll) 
                Type delegateType = sourceAsm.GetType(delegateTypeName);
                //recupero l'evento (dll) 
                EventInfo sourceEvent = sourceType.GetEvent(eventName);
                //recupero il metodo target in questo caso il metodo OnTick di questa classe
                MethodInfo targetMethod = typeof(Form1).GetMethod(methodName,BindingFlags.Public | BindingFlags.Instance);   
                //Creo una istanza del tipo che contiene l'evento (dll)         
                object dllObj = Activator.CreateInstance(sourceType);
                //creo il delegato
                Delegate d = targetMethod.CreateDelegate(delegateType, this);
                //aggiungo il delegato all'evento
                sourceEvent.AddEventHandler(dllObj, d);
            }
    
    
            public void OnTick(dynamic sender, dynamic e)
            {
                MessageBox.Show("Hello");
            }
        }
    }

  3. #3
    Moderatore di Windows e software L'avatar di URANIO
    Registrato dal
    Dec 1999
    residenza
    Casalpusterlengo (LO)
    Messaggi
    1,290
    Fico, questo esempio mi è chiaro, domani lo provo.

  4. #4
    Moderatore di Windows e software L'avatar di URANIO
    Registrato dal
    Dec 1999
    residenza
    Casalpusterlengo (LO)
    Messaggi
    1,290
    mmmm
    Non riesco a fare
    Delegate d = targetMethod.CreateDelegate(delegateType, this);

    Mi dice che CreateDelegate non esiste in methodinfo. La cosa strana è che da documentazione è così.


    ...capito, c'è solo dal framework 4.5 in poi!!!!

    Ho risolto con
    codice:
    Dim wDelegato As [Delegate] = [Delegate].CreateDelegate(wTipoDelegato, wMetodoRichiamato)
    (programmo in VB.NET)

    MA va in errore perchè:
    Ulteriori informazioni: Impossibile eseguire l'associazione al metodo di destinazione perché la firma o la trasparenza della sicurezza non è compatibile con quella del tipo delegato.

    Il problema è che il delegato della dll esterna è:
    delegato(Pippo1 as oggetto1, pippo2 as oggetto2)

    nel mio progetto invece il metodo l'ho fatto usando generici object in questo modo:
    Metodo(pippo1 as object, pippo2 as object)
    (dato che non ho i riferimenti)

    Ultima modifica di URANIO; 21-07-2016 a 10:43

  5. #5
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,539
    Quote Originariamente inviata da URANIO Visualizza il messaggio
    mmmm
    Ho risolto con
    codice:
    Dim wDelegato As [Delegate] = [Delegate].CreateDelegate(wTipoDelegato, wMetodoRichiamato)
    (programmo in VB.NET)

    MA va in errore...

    Ciao

    per quello devi mettere l'istanza in uso:

    Dim d As [Delegate] = [Delegate].CreateDelegate(delegateType, Me, targetMethod)

    codice vb.net per net 4 della classe target:
    codice:
    Imports System.Reflection
    
    Public Class Form1
        Const libraryName = "ClassLibrary1.dll"
        Const typeName = "ClassLibrary1.Class1"
        Const eventName = "Tick"
        Const delegateTypeName = "ClassLibrary1.MyDelegate"
        Const methodName = "OnTick"
    
    
        Public Sub New()
            InitializeComponent()
            'carico l'assembly (dll) 
            Dim sourceAsm As Assembly = Assembly.LoadFrom(libraryName)
            'recupero il tipo che contiene l'evento (dll) 
            Dim sourceType As Type = sourceAsm.[GetType](typeName)
            'recupero il tipo del delegato (dll) 
            Dim delegateType As Type = sourceAsm.[GetType](delegateTypeName)
            'recupero l'evento (dll) 
            Dim sourceEvent As EventInfo = sourceType.GetEvent(eventName)
            'recupero il metodo target in questo caso il metodo OnTick di questa classe
            Dim targetMethod As MethodInfo = GetType(Form1).GetMethod(methodName, BindingFlags.[Public] Or BindingFlags.Instance)
            'Creo una istanza del tipo che contiene l'evento (dll)         
            Dim dllObj As Object = Activator.CreateInstance(sourceType)
            'creo il delegato
            Dim d As [Delegate] = [Delegate].CreateDelegate(delegateType, Me, targetMethod)
            'aggiungo il delegato all'evento
            sourceEvent.AddEventHandler(dllObj, d)
            ' La chiamata è richiesta dalla finestra di progettazione.
        End Sub
    
    
        Public Sub OnTick(sender, e)
            MessageBox.Show("Hello")
        End Sub
    
    
    End Class

  6. #6
    Moderatore di Windows e software L'avatar di URANIO
    Registrato dal
    Dec 1999
    residenza
    Casalpusterlengo (LO)
    Messaggi
    1,290
    Nulla, stesso errore, non mi crea il delegato.
    Secondo me sbaglio in qualcosa di banale.

  7. #7
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,539
    Quote Originariamente inviata da URANIO Visualizza il messaggio
    Nulla, stesso errore, non mi crea il delegato.
    Secondo me sbaglio in qualcosa di banale.
    posso vedere il tuo codice?


    EDIT:
    Domanda: ma il metodo target restituisce lo stesso tipo del delegato?
    Ultima modifica di U235; 21-07-2016 a 14:49

  8. #8
    Moderatore di Windows e software L'avatar di URANIO
    Registrato dal
    Dec 1999
    residenza
    Casalpusterlengo (LO)
    Messaggi
    1,290
    Quote Originariamente inviata da U235 Visualizza il messaggio
    posso vedere il tuo codice?
    E' un pò complesso e lungo, devo fare una versione "Ristretta, appena ho unn pò di tempo posto

    EDIT:
    Domanda: ma il metodo target restituisce lo stesso tipo del delegato?
    Il problema è proprio questo!

    L'evento esterno sulla dll ha questo delegato
    Public Delegate Sub DelegateJobProcessStarted(ByRef server As Server, pc As VCJobProcessClass)

    (Server e VCJobProcessClass sono due classi definite sulla DLL esterna)

    Il mio metodo locale è
    Public sub metodo(primo as object, secondo as object)

  9. #9
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,539
    Quote Originariamente inviata da URANIO Visualizza il messaggio
    E' un pò complesso e lungo, devo fare una versione "Ristretta, appena ho unn pò di tempo posto


    Il problema è proprio questo!

    L'evento esterno sulla dll ha questo delegato
    Public Delegate Sub DelegateJobProcessStarted(ByRef server As Server, pc As VCJobProcessClass)

    (Server e VCJobProcessClass sono due classi definite sulla DLL esterna)

    Il mio metodo locale è
    Public sub metodo(primo as object, secondo as object)
    È il byref che ti frega... Non tanto il tipo. Si potrebbe provare con i generics ma non so se sia possibile.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.