2013-01-03 4 views
5

Ho creato un motore che accetta plugin di terze parti (DLL) che implementano un'interfaccia.È possibile creare un'istanza di una classe senza eseguire QUALSIASI codice dalla classe? (nessun codice, nessuna inizializzazione dei campi)

Poiché non ho alcun controllo sul codice che viene collegato, voglio essere in grado di eseguire 1 metodo specifico (dall'interfaccia) dalla classe corretta (ciclo GetTypes fino a trovare la classe interfacciata).

Dal momento che chiunque può creare bel codice del costruttore che viene eseguito su Activator.CreateInstance, posso risolvere che utilizzando FormatterServices.GetUninitializedObject. Ma questo non aiuta quando il codice viene inizializzato sui campi della classe.

public class myclass : myinterface { 

    public someotherclass name = new someotherclass() 

    public myclass() { 
    //Unknown code 
    } 

    //I only want this run. 
    public string MyProperty{ 
    get { 
     return "ANiceConstString"; 
    } 
    } 
} 

Il problema con entrambi i modi (CreateInstance/GetUninitializedObject) è che il costruttore di verrà eseguito someotherclass.

Prima di iniziare ad analizzare le mie esigenze. Questo viene eseguito solo durante l'inizializzazione del motore per ottenere un set di valori standard. Se questo geter si basa su altri valori inizializzati, il "plug-in" verrà contrassegnato come non riuscito poiché non è stato restituito alcun valore valido. Se non viene contrassegnato come non riuscito, in seguito la classe verrà caricata correttamente con Activator.CreateInstance().

Quindi attenersi a questa domanda: .Net supporta qualsiasi modo per creare una classe non inizializzata al 100%?

Aggiornamento per le risposte. Ho provato questo prima di pubblicare la mia domanda.

Per la risposta che non viene eseguita alcuna cella, l'ho già testata ed è eseguita se statica.

public class myclass : myinterface { 

    static Tutle test; 

    public myclass() { 
     test = new Tutle(); 
    } 

    public class Tutle { 
     public Tutle() { 
      MessageBox.Show("RUN!"); 
     } 
    } 
} 

CreateInstance mostra la finestra di messaggio. GetUninitializedObject no.

public class myclass : myinterface { 

    static Tutle test = new Tutle(); 

    public myclass() { 
    } 

    public class Tutle { 
     public Tutle() { 
      MessageBox.Show("RUN!"); 
     } 
    } 
} 

CreateInstance mostra la finestra di messaggio. GetUninitializedObject mostra la messagebox.

C'è un modo per aggirare gli inquinatori e i sensori di campo statici?

+0

Se non si vuole veramente un'istanza di oggetto da creare, suona come si desidera una * proprietà * statico invece. Sì, significa che non puoi specificarlo in un'interfaccia ... ma stai già utilizzando la riflessione, quindi puoi semplicemente controllare che tutti i tipi abbiano la proprietà pertinente. Oppure, se sai che il valore della proprietà dovrebbe essere sempre una costante, potrebbe invece richiedere un attributo personalizzato. –

+2

Ogni volta che non si ha il controllo del codice che viene eseguito, si potrebbe prendere in considerazione l'esecuzione di quel codice in un AppDomain separato con autorizzazioni limitate. Questa potrebbe essere un'alternativa alla creazione di un oggetto non inizializzato. –

risposta

14

Semplicemente:

var obj = (myclass)FormatterServices.GetUninitializedObject(typeof(myclass)); 

Quello non verrà eseguire gli inizializzatori costruttore/campo. Affatto. È non eseguire il costruttore per someotherclass; name sarà null.

Tuttavia, eseguirà qualsiasi costruttore statico esistente, se necessario in base alle regole .NET standard.

TUTTAVIA! Devo notare che questo metodo non è inteso per l'utilizzo ad-hoc; il suo scopo principale è l'uso in serializzatori e motori remoti. C'è una buona probabilità che i tipi non funzionino correttamente se creati in questo modo, se non si sono successivamente intrapresi dei passi per riportarli in uno stato valido (che qualsiasi motore serializzatore/remoting dovrebbe fare).

+1

Corretto, l'inizializzatore del campo ('public someotherclass name = new someotherclass();' nel tuo esempio) * non * verrà eseguito. –

+0

Controlla il mio aggiornamento. GetUninitializedObject esegue il codice ... Già testato prima di pubblicare. NM. Static era il problema. Quindi non c'è modo di aggirare l'elettricità statica? – Wolf5

+1

@ Wolf5 Ho provato anche io: p e no: non lo è (modifica: questo commento non è più aggiornato poiché ora è contrassegnato come 'statico') –

5

Come una considerazione design alternativo:

[SomeFeature("ANiceConstString")] 
public class myclass : myinterface { 

    public someotherclass name = new someotherclass() 

    public myclass() { 
    //Unknown code 
    } 
} 

Ora è possibile accedere alla funzione senza istanziazione; basta usare:

var attrib = (SomeFeatureAttribute)Attribute.GetCustomAttribute(
    type, typeof(SomeFeatureAttribute)); 
string whatever = attrib == null ? null : attrib.Name; 

con:

[AttributeUsage(
    AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)] 
public sealed class SomeFeatureAttribute : Attribute 
{ 
    private readonly string name; 
    public string Name { get { return name; } } 
    public SomeFeatureAttribute(string name) { this.name = name; } 
} 
+0

Grazie. Penso che lo aggiungerò. Poiché l'interfaccia è pubblicata e impostata, posso fare un pre-controllo se l'attributo è impostato e usarlo prima di creare un'istanza. Retrocompatibilità. – Wolf5

+0

Mi piace molto meglio. 'GetUninitializedObject' sembra molto pericoloso! –

Problemi correlati