350 messaggi dal 08 febbraio 2009
Salve a tutti.

Sto provando a creare un gestore di stampe. Attualmente ho un controllo del seguente tipo:

 
switch (estensione) 
{ 
      case ".PDF": 
          stampo PDF 
      case ".BMP": 
         stampo BMP 
} 
 



Attualmente ho implementato la stampa in base all'estensione del file, però ovviamente implemento i metodi per "estensioni" che conosco.
(mi funziona tutto, voglio solo provare a fare qualcosa di più "implementabile").


Quello che volevo riuscire a fare è quello di caricare, partendo da una cartella, le varie classi che mi servono.

ESEMPIO:

Supponiamo che io abbia la cartella "C:\Libreria\Stampe" in cui devo mettere le DLL da usare come stampa.
Ovviamente, tutte le DLL devono implementare una specifica interfaccia (supponiamo IPrint).

Quindi, nel mio programma, inserire una logica del tipo:

-) Cerca nella directory il file "xxxPrintHelper.dll" dove xxx è l'estensione.
-) Se esiste, allora carica "a runtime" quella dll come IPrint e lancia il metodo per la stampa
-) Se non esiste (o non implementa IPrint), allora cerca DefaultPrintHelper.dll
-) Se nemmeno quello è valido, stampa mediante "PrintTo" (verb)


In questo modo, il mio servizio di stampa sarebbe "facilmente" implementabile...
Purtroppo ho visto molti esempi di Reflection in giro, però non ho ben capito come poter caricare una DLL senza averla fra i riferimenti del mio progetto...

Qualcuno mi può dire se è fattibile e magari farmi un piccolo esempio veloce?

Grazie mille
http://
Ciao,

è molto semplice:
var assembly = Assembly.LoadFrom("filename");
Type type = assembly.GetType("typeName");
IPrint res = (IPrint) Activator.CreateInstance(type);

return res;

m.
350 messaggi dal 08 febbraio 2009
Ciao.

Ho fatto una semplice prova usando un unico progetto e tutto funziona bene.
Se però creo due progetti sotto la stessa soluzione, le cose non vanno.

Esempio:

Soluzione "ConsoleApplication"

-------------------
Progetto MyAssembly
-------------------

(cartella Interfaces)

namespace MyAssembly.Interfaces
{
    public interface IPrint
    {
        bool Print();
    }
}



Senza cartella

namespace MyAssembly
{
    class PrintClass : IPrint
    {
        #region IPrint Membri di

        public bool Print()
        {
            return true;
        }

        #endregion
    }
}


------------------------
Progetto ConsoleApplication
------------------------

using System.
using System.Text;
using System.Reflection;
using MyAssembly.Interfaces;
using MyAssembly;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Assembly a = Assembly.LoadFrom("C:\\Users\\Gianni\\Documents\\Visual Studio 2008\\Projects\\ConsoleApplication\\MyAssembly\\bin\\Release\\MyAssembly.dll");
            Type t = a.GetType("MyAssembly.PrintClass");
            IPrint p = Activator.CreateInstance(t) as IPrint;
            if (p == null)
            {
                Console.WriteLine("null");
            }
            else
            {
                Console.WriteLine(p.Print());
            }
            Console.ReadLine();
        }
    }
}



Lasciando "ConsoleApplication" come progetto principale, se eseguo il tutto, viene visualizzato "null", il chè vuol dire che P non viene istanziato.

Se porto le interfacce all'interno dello stesso assembly (ConsoleApplication), allora funziona tutto correttamente.

Quale può essere il problema?
ma quel MyAssembly che referenzi è lo stesso che poi carichi dinamicamente?

Guarda, così su due piedi non so dirti, probabilmente la ragione è che la classe che istanzi non imprementa quella stessa IPrint a cui stai facendo il cast, ma comunque mi sembra un esempio poco consistente!

Tu dovresti avere una situazione di questo tipo:
1) Assembly con interfaccia IPrint
2) ConsoleApp che referenzia 1
3) Assembly esterno che referenzia 1 e contiene l'implementazione di IPrint

Ciao,
m.
350 messaggi dal 08 febbraio 2009
Nel caso specifico, MyAssembly contiene sia la definizione di IPrint, sia la sua implementazione (ovvero una classe che implementa quella interfaccia).

Poi ho il progetto ConsoleApplication che carica dinamicamente MyAssembly per caricare il tutto.

Pensavo di mettere l'interfaccia ed alcune implementazioni nello stesso Assembly, così se un "terzo" vuole estendere delle mie classi lo può fare...

Se ti condivido via FTP il progetto (sono 50 righe di codice in totale come vedi dagli esempi), riesci a darci un'occhiata? (con calma, non è una cosa che devo risolvere in fretta, tanto lo sto facendo "per sfizio", non ho commesse di lavoro o altro)

E' fatto in C# express 2008... Ci sarebbe solo da cambiare il path da cui carica l'assembly (perchè ovviamente essendo PC diversi è difficile che il percorso sia lo stesso).

Per essere ho un PC con 7 (si sa mai che sia quello ad avere problemi).
Joe, scusa, ma prima di condividere i progetti e darci le occhiate, perchè non provi a fare un test consistente come ti ho descritto nell'ultimo post? No, perchè tu ora come ora stai caricando dinamicamente un assembly che già referenzi (lo vedo dalle using), e non mi sembra una cosa tanto sensata!

Ciao,
m.
350 messaggi dal 08 febbraio 2009
Solo per vedere se ho capito bene:

1) Creo un Assembly solo con le interfaccie (diciamo progetto MyInterfaces). Questo servirà ad eventuali "terzi" per poter creare le loro classi personalizzate in base alle loro gestioni.

2) Creo un Assembly con le mie classi che implementano le interfaccie di cui al punto 1 (diciamo progetto MyClasses). In pratica faccio il lavoro che poi faranno anche "i terzi".

3) Creo un Assembly che carica dinamicamente l'assembly del punto 2 (LoadFrom) e poi fa il cast usando le interfaccie del punto 1.


E' giusto come "giro"?
Stando a quello che mi dici, potrebbe essere che il runtime vada in confusione perchè, nell'esempio postato, ho referenziato delle interfaccie che poi vado anche a caricare dinamicamente (perchè presenti nello stesso assembly che carico).


Se così fosse, ho capito perchè dici "non è una situazione reale". Il fatto è che non avevo colto questa "finezza" leggendo il tuo post la prima volta... Poi ho provato a ragionarci sopra e, se quello che ho scritto sopra è corretto, forse ho capito anche la logica che ci sta dietro... (che è la cosa che poi mi ha spinto a creare tale progetto di test).

Grazie mille e scusa il disturbo!!!!
Figurati, nessun disturbo!

Hai colto nel segno, fammi sapere se così funziona!

Ciao,
m.

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.
In primo piano

I più letti di oggi

Media
In evidenza
MISC