Question

J'ai actuellement ce type de code:

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

Si l'on suppose que SomeClassType1 et SomeClassType2 ont le même ensemble de propriétés que je veux attribuer (bien qu'ils peuvent différer autres), est-il possible de lancer dynamiquement MainObject au type approprié et puis attribuez-lui la valeur, sans dupliquer le code ? Voilà ce que je voudrais voir à la fin:

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

Et, évidemment, C # se plaint de ne pas être en mesure de trouver DynamicType:

  

n'a pas pu être trouvé le type ou le nom d'espace de noms « de DynamicType » (vous manque une directive à l'aide ou une référence d'assemblage?)

est quelque chose comme cela possible en C # 2.0? Si elle est plus salissant que mon code actuel, que je ne vois pas à faire cela, mais je suis très intéressé de savoir. Merci!

EDIT: Juste pour clarifier, je comprends parfaitement que la mise en œuvre d'une interface est la solution la plus appropriée et probablement correcte. Cela dit, je suis plus intéressé à voir comment je pouvais le faire sans mettre en œuvre une interface. Merci pour les réponses grands!

Était-ce utile?

La solution

On dirait que les deux types que vous aimez mettre en œuvre sur les deux mêmes propriétés. Dans ce cas, ce que vous voulez faire est de définir une interface pour ces propriétés:

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

Ensuite, assurez-vous que chacune de vos classes dire au compilateur qu'ils mettent en œuvre cette nouvelle interface. Enfin, utilisez une méthode générique avec un argument de type qui est contraint à cette interace:

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

Notez que même avec le code supplémentaire pour déclarer l'interface, ces extraits finissent toujours plus court que l'un des extraits où vous avez posté la question, et ce code est beaucoup plus facile d'étendre si le nombre de types que vous se soucient de l'augmentation .

Autres conseils

Essentiellement ce que vous faites ici est d'écrire une instruction switch en fonction du type fo l'objet. Il n'y a pas en soi une bonne façon de le faire autre que votre premier exemple (ce qui est au mieux fastidieux).

J'ai écrit un petit cadre pour la mise sous tension des types qui rend la syntaxe un peu plus concise. Il vous permet d'écrire du code comme suit.

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 Post: http: // blogs .msdn.com / JaredPar / archive / 2008/05/16 / commutation sur-types.aspx

Serez-vous capable d'apporter des modifications à SomeClassType1, SomeClassType2 etc? Si oui, alors je suggère que vous créez une interface contenant vos propriétés communes puis typecast à cette interface dans FillObject() pour définir les propriétés.

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

Quelques idées:

  1. les deux types hériter du même type qui ont les propriétés communes
  2. les deux types implémenter la même interface qui ont les propriétés communes
  3. Utiliser la réflexion pour définir les propriétés plutôt que de les mettre directement (ce qui est probablement plus laid que cela vaut la peine)
  4. Utilisez la nouvelle dynamique fonction, je n'ai pas essayé, mais il semble que cela pourrait résoudre votre problème

Au lieu d'essayer de jeter, vous pourriez peut-être essayer de définir les propriétés utilisant la réflexion.

Je suis coulée dynamiquement des objets en utilisant la réflexion dans une application ASP.NET MVC. Fondamentalement, j'énumérer les propriétés d'une classe, trouver la valeur correspondante dans la banque de données et dynamiquement jeter la valeur et l'affecter à l'instance d'objet. Voir mon blog casting dynamique avec .NET

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top