2008-10-16 21 views
13

tengo una clase que tiene la siguiente constructorActivator.CreateInstance no puede encontrar el constructor (MissingMethodException)

public DelayCompositeDesigner(DelayComposite CompositeObject) 
{ 
    InitializeComponent(); 

    compositeObject = CompositeObject; 
} 

junto con un constructor predeterminado sin parámetros.

siguiente estoy tratando de crear una instancia, pero sólo funciona sin parámetros:

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

Esto funciona muy bien, pero si quiero pasar parámetros no es así:

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

Esto resulta en un MissingMethodException:

tipo Constructor voor Vialis.LightLink.Controll er.Scenarios.Composites.DelayCompositeDesigner no se encontró

¿Alguna idea aquí?


El problema es que realmente necesito pasar un objeto durante la construcción.

Usted ve que tengo un diseñador que carga todos los tipos que heredan del CompositeBase. Estos se agregan a una lista desde la cual los usuarios pueden arrastrarlos a un diseñador. Al hacerlo, se agrega una instancia del arrastre al diseñador. Cada una de estas clases tienen propiedades personalizadas definidas en ellos:

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

Cuando el usuario selecciona un elemento en el diseñador, que mira a estos atributos con el fin de cargar hasta un diseñador para ese tipo. Por ejemplo, en el caso del DelayComposite cargaría un control de usuario que tiene una etiqueta y un control deslizante que permiten al usuario establecer la propiedad "Retraso" de la instancia DelayComposite.

Hasta ahora, esto funciona bien si no paso ningún parámetro al constructor. El diseñador crea una instancia del DelayCompositeDesigner y la asigna a la propiedad de contenido de un WPF ContentPresenter.

Pero como ese diseñador necesita modificar las propiedades del DelayComposite seleccionado en el diseñador, tengo que pasarle esta instancia. Es por ello que el constructor parece estar presente:

public DelayCompositeDesigner(DelayComposite CompositeObject) 
{ 
    InitializeComponent(); 

    compositeObject = CompositeObject; 
} 

sugerencias son bienvenidas


@VolkerK

El resultado de su código es la siguiente:

< --- - foo 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 foo ---->


leppie, usted tenía razón, había por alguna razón hace referencia el conjunto de composites en mi aplicación de interfaz de usuario ... que no es algo que debería tener hecho mientras lo cargaba en tiempo de ejecución. El siguiente código funciona:

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

Como se puede ver el código no tiene conocimiento del tipo DelayComposite.

Esto resuelve el problema actual, pero introduce muchos nuevos para lo que quiero lograr, de cualquier manera, gracias y gracias a todos los que han respondido aquí.


En cuanto al siguiente código, sugerido por varias personas:

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

El Activator.CreateInstance tiene una firma que tiene este aspecto:

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

por lo que debe aceptar mi código, pero Voy a intentar el código sugerido

ACTUALIZACIÓN:

He intentado esto como se sugiere:

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

El resultado es el mismo.

+0

Timoteo - He modificado mi respuesta para pasar typeof (DelayCompositeDesigner) ... o tal vez todavía me falta una pieza del rompecabezas. – Kev

+0

¿Puede ampliar cómo se declara designerAttribute.Designer? – Kev

+0

Timothy - ¿es designerAttribute.Designer declarado como Type? – Kev

Respuesta

13

Creo que se trata de un tipo no coincidente.

Es probable que el ensamblaje esté referenciado en diferentes lugares o compilados contra diferentes versiones.

Le sugiero que itere a través de ConstructorInfo y haga un paramtype == typeof(DelayComposite) en el parámetro apropiado.

+0

Puede que haya algo aquí .... Verificare – TimothyP

12

Me gustaría pensar que su llamada tendría que ser:

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

A menos que, por supuesto, es que, en cuyo caso la respuesta no es inmediatamente evidente.

+1

Esto funcionó perfectamente para mí, ¡solo solucione el problema! – Spikeh

0

Descubrí otra forma de crear una instancia de un objeto sin llamar al constructor mientras que answering otra pregunta sobre SF.

En el espacio de nombres System.Runtime.Serialization hay una función FormatterServices.GetUninitializedObject (tipo) que va a crear un objeto sin llamar al constructor.

Si observa esa función en Reflector, verá que está realizando una llamada externa. No sé cómo la magia negra está sucediendo bajo el capó. Pero me demostré a mí mismo que el constructor nunca fue llamado, pero el objeto fue instanciado.

0

Usted puede utilizar el siguiente sobrecarga en CreateInstance:

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

Y en su caso sería (creo):

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

He intentado esto, pero no funciona. Además, no es necesario crear un nuevo objeto [] – TimothyP

+0

De hecho, tengo una situación en la que se necesita el nuevo objeto []. El tipo de parámetro (único) en mi constructor es un Tuple [] y solo cuando lo paso como un elemento único objeto [] encuentra el constructor. – Han

3

Si desea llamar a este contructor ...

public DelayCompositeDesigner(DelayComposite CompositeObject) 

... sólo tiene que utilizar esto:

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

o

var designer = Activator.CreateInstance<DelayCompositeDesigner>(new DelayComposite(4)); 
+0

designerAttribute.Designer parece ser = typeof (DelayCompositeDesigner) – VolkerK

+0

Ishmaeel: cuando está creando una instancia de DelayCompositeDesigner, necesita usar el DelayCompositeDesigner (DelayComposite CompositeObject). No hay una sobrecarga en CreateInstance() para el ejemplo dado. – Kev

+0

De hecho: designerAttribute.Designer es ese tipo, ya que no tengo ni idea de lo que será. No puedo usar = typeof (DelayCompositeDesigner) – TimothyP

5

Aunque odio printf-como la depuración ...

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)); 

lo que hace que la letra impresa en la ventana de salida del estudio visual?

0

Encontré una solución al problema, estaba luchando con el mismo problema.

Aquí es mi activador:

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); 
      } 
     } 
    } 

Y aquí es mi clase para activar, nota que tenía que cambiar los parametros del constructor de objetos, la única manera de que pudiera conseguir que funcione.

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" }); 
    } 
} 
Cuestiones relacionadas