Pregunta

Actualmente tengo este tipo de código:

private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
    if (MainObject is SomeClassType1)
    {
        SomeClassType1 HelpObject = (SomeClassType1)MainObject;
        HelpObject.Property1 = Arg1;
        HelpObject.Property2 = Arg2;
    }
    else if (MainObject is SomeClassType2)
    {
        SomeClassType2 HelpObject = (SomeClassType2)MainObject;
        HelpObject.Property1 = Arg1;
        HelpObject.Property2 = Arg2;
    }
}

Suponiendo que SomeClassType1 y SomeClassType2 tienen el mismo conjunto de propiedades que desea asignar (aunque pueden diferir en otras), es posible emitir dinámicamente MainObject al tipo apropiado y luego asignar el valor, sin duplicar el código ? Esto es lo que me gustaría ver en el final:

private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
    Type DynamicType = null;

    if (MainObject is SomeClassType1)
    {
        DynamicType = typeof(SomeClassType1);
    }
    else if (MainObject is SomeClassType2)
    {
        DynamicType = typeof(SomeClassType2);
    }

    DynamicType HelpObject = (DynamicType)MainObject;
    HelpObject.Property1 = Arg1;
    HelpObject.Property2 = Arg2;
}

Y, obviamente, C # se queja de no poder encontrar DynamicType:

  

El tipo o espacio de nombres 'DynamicType' no se pudo encontrar (¿falta una directiva using o una referencia de ensamblado?)

Es algo como esto sea posible en C # 2.0? Si es más sucio que mi código actual, que no veo ninguna razón para hacer esto, pero estoy muy interesado en saber. Gracias!

EDIT: Solo para aclarar, entiendo perfectamente que la implementación de una interfaz es la solución más adecuada y probablemente correcta. Dicho esto, estoy más interesado en ver cómo podía hacerlo sin implementar una interfaz. Gracias por grandes respuestas!

¿Fue útil?

Solución

Parece que ambos tipos se preocupa por aplicar los mismos dos propiedades. En ese caso, lo que se quiere hacer es definir una interfaz para aquellas propiedades:

public interface IMyInterface
{
   public Foo Property1 {get; set;}
   public Bar Property2 {get;set;}
}

A continuación, asegúrese de que cada una de sus clases indicar al compilador que aplican ese nuevo interfaz. Por último, utilizar un método genérico con un argumento tipo que está restringido a que interace:

private void FillObject<T>(T MainObject, Foo Arg1, Bar Arg2) 
    where T : IMyInterface
{
    MainObject.Property1 = Arg1;
    MainObject.Property2 = Arg2;
}

Tenga en cuenta que incluso con el código adicional para declarar la interfaz, estos fragmentos aún así terminar más corto que sea uno de los fragmentos en los que posteaste la cuestión, y este código es mucho más fácil de extender, si el número de tipos que se preocupan por los aumentos .

Otros consejos

En esencia lo que estamos haciendo aquí es escribir una sentencia switch basado en el tipo FO el objeto. No hay ninguna inherentemente buena manera de hacer esto que no sea su primer ejemplo (que es tedioso en el mejor).

escribí un pequeño marco para la conexión de los tipos que hacen que la sintaxis un poco más concisa. Se le permite escribir código como el siguiente.

TypeSwitch.Do(
    sender,
    TypeSwitch.Case<Button>(
        () => textBox1.Text = "Hit a Button"),
    TypeSwitch.Case<CheckBox>(
        x => textBox1.Text = "Checkbox is " + x.Checked),
    TypeSwitch.Default(
        () => textBox1.Text = "Not sure what is hovered over"));

Blog de la publicación: http: // blogs .msdn.com / JaredPar / archivo / 2008/05/16 / conmutación-en-types.aspx

¿Quieres ser capaz de realizar cambios en SomeClassType1, SomeClassType2 etc? Si sí, entonces voy a sugerir que se crea una interfaz que contiene sus propiedades comunes y luego encasillado a esta interfaz dentro FillObject() para establecer las propiedades.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SO566510
{
    interface IMyProperties
    {
        int Property1 { get; set; }
        int Property2 { get; set; }
    }

    class SomeClassType1 : IMyProperties
    {
        public int Property1 { get; set; }
        public int Property2 { get; set; }
    }

    class SomeClassType2 : IMyProperties
    {
        public int Property1 { get; set; }
        public int Property2 { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var obj1 = new SomeClassType1();
            var obj2 = new SomeClassType2();

            FillObject(obj1, 10, 20);
            FillObject(obj2, 30, 40);

        }

        private static void FillObject(IMyProperties objWithMyProperties
                                   , int arg1, int arg2)
        {
            objWithMyProperties.Property1 = arg1;
            objWithMyProperties.Property2 = arg2;
        }
    }
}
private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
    Type t = MainObject.GetType();

    t.GetProperty("Property1").SetValue(MainObject, Arg1, null);
    t.GetProperty("Property2").SetValue(MainObject, Arg2, null);
}

Algunas ideas:

  1. Haga que ambos tipos heredar del mismo tipo que tiene las propiedades comunes
  2. tienen ambos tipos implementar la misma interfaz que tiene las propiedades comunes
  3. Uso de reflexión para establecer las propiedades en vez de hacerlo directamente (esto es probablemente más fea de lo que vale)
  4. Utilice la nueva dinámico función , no he probado esto, pero parece que podría abordar el problema

En lugar de tratar de fundido, tal vez usted podría intentar establecer las propiedades utilizando la reflexión.

Estoy dinámicamente Conversión de objetos que utilizan la reflexión en una aplicación ASP.NET MVC. Básicamente Enumero las propiedades de una clase, encontrar el valor correspondiente en el almacén de datos de forma dinámica y convertir el valor y asignarlo a la instancia del objeto. Ver mi blog dinámico de fundición con .NET

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