Domanda

Ho una classe che ha il seguente costruttore

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;  
}

insieme a un costruttore predefinito senza parametri.

Quindi sto cercando di creare un'istanza, ma funziona solo senza parametri:

var designer = Activator.CreateInstance(designerAttribute.Designer);

Funziona bene, ma se voglio passare parametri non lo fa:

var designer = Activator.CreateInstance(designerAttribute.Designer, new DelayComposite(4));

Ciò si traduce in un MissingMethodException:

  

Costruttore voor type   Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesigner   non è stato trovato

Qualche idea qui?


Il problema è che ho davvero bisogno di passare un oggetto durante la costruzione.

Vedi, ho un designer che carica tutti i tipi che ereditano dal CompositeBase. Questi vengono quindi aggiunti a un elenco dal quale gli utenti possono trascinarli su un designer. Facendo così un'istanza del trascinato viene aggiunta al designer. Ognuna di queste classi ha proprietà personalizzate definite su di esse:

[CompositeMetaData("Delay","Sets the delay between commands",1)]
[CompositeDesigner(typeof(DelayCompositeDesigner))]
public class DelayComposite : CompositeBase
{
}

Quando l'utente seleziona un elemento nel designer, esamina questi attributi per caricare un designer per quel tipo. Ad esempio, nel caso di DelayComposite caricherà un controllo utente che ha un'etichetta e un dispositivo di scorrimento che consente all'utente di impostare & Quot; Delay & Quot; proprietà dell'istanza DelayCompositeDesigner.

Finora funziona bene se non passo parametri al costruttore. Il designer crea un'istanza di ContentPresenter e la assegna alla proprietà content di un WPF Activator.CreateInstance.

Ma dal momento che quel designer deve modificare le proprietà del <=> selezionato nel designer, devo passare questa istanza ad esso. Ecco perché il costruttore sembra mentire questo:

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;
}

I suggerimenti sono ben accetti


@VolkerK

Il risultato del tuo codice è questo:

  

< ---- pippo   Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid   .ctor ()   Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid   .ctor (Vialis.LightLink.Controller.Scenarios.Composites.DelayComposite)   param: Vialis.LightLink.Controller.Scenarios.Composites.DelayComposite   pippo ---- >


Leppie, avevi ragione, per qualche motivo avevo fatto riferimento all'assembly Composites nella mia applicazione UI ... che non è qualcosa che avrei dovuto fare mentre lo stavo caricando in fase di esecuzione. Il seguente codice funziona:

object composite = Activator.CreateInstance(item.CompositType,(byte)205);
                    var designer = Activator.CreateInstance(designerAttribute.Designer, composite);

Come puoi vedere, il codice non è a conoscenza del tipo <=>.

Questo risolve il problema attuale, ma introduce molti nuovi per quello che voglio raggiungere, in entrambi i casi, grazie e grazie a tutti coloro che hanno risposto qui.


Come per il seguente codice, suggerito da più persone:

var designer = Activator.CreateInstance(
    designerAttribute.Designer, 
    new object[] { new DelayComposite(4) } 
);

Il <=> ha una firma simile a questa:

Activator.CreateInstance(Type type, params object[] obj)

Quindi dovrebbe accettare il mio codice, ma proverò il codice suggerito

UPDATE:

Ho provato questo come suggerito:

var designer = Activator.CreateInstance(designerAttribute.Designer, new object[] { new DelayComposite(4)});

Il risultato è lo stesso.

È stato utile?

Soluzione

Penso che tu abbia a che fare con una mancata corrispondenza del tipo.

Probabilmente si fa riferimento all'assembly in luoghi diversi o vengono compilati in versioni diverse.

Ti suggerisco di passare da ConstructorInfo a e di fare un paramtype == typeof(DelayComposite) sul parametro appropriato.

Altri suggerimenti

Penso che la tua chiamata dovrebbe essere:

var designer = Activator.CreateInstance(designerAttribute.Designer, new object[] { new DelayComposite(4) });

A meno che, ovviamente, sia che, nel qual caso la risposta non sia immediatamente ovvia.

Anche se odio il debug simile a printf ...

public static void foo(Type t, params object[] p)
{
    System.Diagnostics.Debug.WriteLine("<---- foo");
    foreach(System.Reflection.ConstructorInfo ci in t.GetConstructors())
    {
        System.Diagnostics.Debug.WriteLine(t.FullName + ci.ToString());
    }
    foreach (object o in p)
    {
        System.Diagnostics.Debug.WriteLine("param:" + o.GetType().FullName);
    }
    System.Diagnostics.Debug.WriteLine("foo ---->");
}
// ...
foo(designerAttribute.Designer, new DelayComposite(4));
var designer = Activator.CreateInstance(designerAttribute.Designer, new DelayComposite(4));

Cosa stampa nella finestra di output di Visual Studio?

Se vuoi chiamare questo costruttore ... ... usa questo:

public DelayCompositeDesigner(DelayComposite CompositeObject)

o

var designer = Activator.CreateInstance(typeof(DelayCompositeDesigner), new DelayComposite(4));

Ho avuto un problema simile, tuttavia il mio problema era dovuto alla visibilità del costruttore. Questo overflow dello stack mi ha aiutato:

Creare un'istanza di un costruttore con parametri in un classe interna con riflessione

Ho scoperto un altro modo di creare un'istanza di un oggetto senza chiamare affatto il costruttore mentre rispondendo un'altra domanda su SF.

Nello spazio dei nomi System.Runtime.Serialization c'è una funzione FormatterServices.GetUninitializedObject (tipo) che creerà un oggetto senza chiamare il costruttore.

Se guardi quella funzione in Reflector vedrai che sta effettuando una chiamata esterna. Non so come la magia nera stia realmente accadendo sotto il cofano. Ma ho dimostrato a me stesso che il costruttore non è mai stato chiamato ma l'oggetto è stato istanziato.

È possibile utilizzare il seguente sovraccarico su CreateInstance:

public static Object CreateInstance(
    Type type,
    Object[] args
)

E nel tuo caso sarebbe (penso):

var designer = Activator.CreateInstance(
    typeof(DelayCompositeDesigner), 
    new object[] { new DelayComposite(4) } 
);

Ho trovato una soluzione al problema, stavo lottando con lo stesso problema.

Ecco il mio attivatore:

private void LoadTask(FileInfo dll)
    {
        Assembly assembly = Assembly.LoadFrom(dll.FullName);

        foreach (Type type in assembly.GetTypes())
        {
            var hasInterface = type.GetInterface("ITask") != null;

            if (type.IsClass && hasInterface)
            {
                var instance = Activator.CreateInstance(type, _proxy, _context);
                _tasks.Add(type.Name, (ITask)instance);
            }
        }
    }

Ed ecco la mia classe da attivare, nota che dovevo cambiare i parametri del costruttore in oggetti, l'unico modo per farlo funzionare.

public class CalculateDowntimeTask : Task<CalculateDowntimeTask>
{
    public CalculateDowntimeTask(object proxy, object context) : 
        base((TaskServiceClient)proxy, (TaskDataDataContext)context) { }

    public override void Execute()
    {
        LogMessage(new TaskMessage() { Message = "Testing" });
        BroadcastMessage(new TaskMessage() { Message = "Testing" });
    }
}

Quando ho riscontrato questo problema, stavo usando un metodo che restituiva l'elenco dei parametri da collegare ad Activator.CreateInstance e aveva un numero di argomenti diverso rispetto al costruttore dell'oggetto che stavo cercando di creare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top