Domanda

Al momento ho questo tipo di codice:

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

Supponendo che SomeClassType1 e SomeClassType2 hanno lo stesso insieme di proprietà che voglio assegnare (anche se possono differire in altri quelli), è possibile colare dinamicamente MainObject al tipo appropriato e quindi assegnare il valore, senza duplicare il codice ? Questo è quello che vorrei vedere alla fine:

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

E ovviamente C # si lamenta di non essere in grado di trovare DynamicType:

  

Il tipo o il nome del namespace 'DynamicType' non è stato trovato (le manca un un riferimento all'assembly direttiva using o?)

E 'qualcosa di simile a questo possibile in C # 2.0? Se è più disordinato che il mio codice corrente, che vedo nessun punto nel fare questo, ma io sono molto interessato a scoprire. Grazie!

EDIT: Giusto per chiarire, Capisco perfettamente che l'attuazione di un interfaccia è la soluzione più appropriata e probabilmente corretto. Detto questo, io sono più interessato a vedere come avrei potuto farlo senza implementare un'interfaccia. Grazie per grandi risposte!

È stato utile?

Soluzione

Sembra che entrambi i tipi che ti interessano implementare le stesse due proprietà. In questo caso, ciò che si vuole fare è definire un'interfaccia per quelle proprietà:

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

Quindi, assicurarsi che ciascuna delle vostre classi dire al compilatore che implementano questa nuova interfaccia. Infine, utilizzare un metodo generico con un argomento di tipo che è costretto a che interace:

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

Si noti che anche con il codice aggiuntivo per dichiarare l'interfaccia, questi frammenti ancora finire più breve di uno dei due frammenti in cui hai postato la domanda, e questo codice è molto più facile per estendere, se il numero di tipi che si preoccupa di aumenti .

Altri suggerimenti

In sostanza quello che stai facendo qui sta scrivendo un'istruzione switch in base al tipo fo l'oggetto. Non v'è alcun intrinsecamente buon modo per fare questo diverso dal primo esempio (che è noioso nel migliore dei casi).

ho scritto un piccolo quadro per l'accensione tipi che rende la sintassi un po 'più concisa. Esso consente di scrivere codice come il seguente.

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

Post: http: // blogs .msdn.com / jaredpar / archive / 2008/05/16 / accensione-types.aspx

Si sarà in grado di apportare modifiche al SomeClassType1, SomeClassType2 ecc? Se sì allora vi suggerisco di creare un'interfaccia contenente le proprietà comuni e poi typecast a questa interfaccia all'interno FillObject() per impostare le proprietà.

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

Alcune idee:

  1. Avere entrambi i tipi di ereditare dalla stesso tipo che hanno le proprietà comuni
  2. hanno entrambi i tipi di implementare la stessa interfaccia che hanno le proprietà comuni
  3. Usa riflessione per impostare le proprietà piuttosto che impostare direttamente (questo è probabilmente più brutto di quel che vale)
  4. Utilizzare il nuovo dinamica caratteristica , non ho provato questo, ma sembra che potrebbe risolvere il problema

Invece di cercare di gettare, forse si potrebbe provare a impostare le proprietà utilizzando la riflessione.

Io sono dinamicamente sull'inserimento di oggetti utilizzando la riflessione in un app ASP.NET MVC. Fondamentalmente enumero le proprietà di una classe, trovare il valore corrispondente nell'archivio dati e gettato dinamicamente il valore e assegnare alla istanza di oggetto. Vedere il mio post sul blog Casting dinamica con .NET

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