Pregunta

Tengo una clase que tiene el siguiente constructor.

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;  
}

junto con un constructor predeterminado sin parámetros.

A continuación intento crear una instancia, pero solo funciona sin parámetros:

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

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

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

Esto resulta en una MissingMethodException:

Constructor Voor Type Vialis.lightlink.controller.scenarios.composites.delayCompositedSigner no se encontró

¿Alguna idea aquí?


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

Verás, tengo un diseñador que carga todos los tipos que heredan del CompositeBase.Luego se agregan a una lista desde la cual los usuarios pueden arrastrarlos a un diseñador.Al hacerlo, se agrega una instancia de lo arrastrado al diseñador.Cada una de estas clases tiene propiedades personalizadas definidas en ellas:

[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, mira estos atributos para cargar un diseñador para ese tipo.Por ejemplo, en el caso de la DelayComposite cargaría un control de usuario que tiene una etiqueta y un control deslizante que permite al usuario establecer la propiedad "Retraso" del DelayComposite instancia.

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

Pero como ese diseñador necesita modificar las propiedades del objeto seleccionado DelayCompositeen el diseñador, tengo que pasarle esta instancia.Es por eso que el constructor se ve así:

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;
}

Se aceptan sugerencias


@VolkerK

El resultado de tu código es este:

<---- foo vialis.lightlink.controller.scenarios.composites.delayCompositedesIgnEnervoid .ctor () vialis.lightlink.controller.scenarios.composites.delayCompositedesigneServoid (vialis.lightlink.controller.scenario.composites.delayeseNEDEDE. .Lightlink.controller.scenarios.composites.delaycomposite foo ---->


Leppie, tenías razón, por alguna razón había hecho referencia al ensamblaje Composites en mi aplicación de interfaz de usuario...lo cual no es algo que debería haber hecho mientras lo estaba cargando 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 puedes ver el código no tiene conocimiento del DelayComposite tipo.

Esto resuelve el problema actual, pero presenta 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 se parece a esta:

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

Entonces debería aceptar mi código, pero probaré el código sugerido.

ACTUALIZAR:

Probé esto como se sugiere:

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

El resultado es el mismo.

¿Fue útil?

Solución

Creo que se trata de una falta de coincidencia de tipos.

Probablemente se haga referencia al ensamblaje en diferentes lugares, o se compilan en diferentes versiones.

Te sugiero que recorras los ConstructorInfo's y hagas un paramtype == typeof(DelayComposite) en el parámetro apropiado.

Otros consejos

Creo que su llamada debería ser:

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

A menos, por supuesto, que sea eso, en cuyo caso la respuesta no es inmediatamente obvia.

Aunque odio la depuración tipo 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));

¿Qué imprime eso en la ventana de salida del estudio visual?

Si desea llamar a este constructor ... ... simplemente use esto:

public DelayCompositeDesigner(DelayComposite CompositeObject)

o

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

Tuve un problema similar, sin embargo, mi problema se debía a la visibilidad del constructor. Este desbordamiento de pila me ayudó:

Creación de una instancia de un constructor con parámetros en una clase interna con reflexión

Descubrí otra forma de crear una instancia de un objeto sin llamar al constructor en absoluto mientras respondiendo otra pregunta sobre SF.

En el espacio de nombres System.Runtime.Serialization hay una función FormatterServices.GetUninitializedObject (type) que 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 está sucediendo realmente la magia negra bajo el capó. Pero me probé a mí mismo que el constructor nunca fue llamado pero el objeto fue instanciado.

Puede usar la siguiente sobrecarga en CreateInstance:

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

Y en tu caso sería (creo):

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

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

Aquí está 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í está mi clase para activar, tenga en cuenta que tuve que cambiar los parámetros del constructor a objetos, la única forma en que podría hacerlo funcionar.

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

Cuando encontré este problema, estaba usando un método que devolvía la lista de parámetros para enchufarlo en Activator.CreateInstance y tenía un número de argumentos diferente al del constructor del objeto que estaba tratando de crear.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top