Question

J'essaie de construire un objet qui ressemble à ceci:

  public class MyObject
  {
    private IList<AnotherObject> items;
    public List<AnotherObject> Items
    {
      return items.AsEnumerable().ToList<AnotherObject>();
    }
  }

J'utilise NHibernate comme DAL et le mappe directement vers le champ des éléments et tout ce qui fonctionne correctement.

J'utilise également Windows Workflow et l'activité de réplicateur ne fonctionne pas avec IList générique. ( http: // social .msdn.microsoft.com / Forums / fr-fr / windowsworkflowfoundation / thread / 2ca74b60-fd33-4031-be4b-17a79e9afe63 ) Cela me force essentiellement à utiliser la liste < > wrapper à la place de IList < > ;. Bien entendu, cela rompt la cartographie directe de NHibernate, car la mise en œuvre IList de NHibernate ne peut pas être directement convertie en liste.

** EDIT: L'exigence de flux de travail Windows signifie en réalité que je vais perdre l'accès à la liste en toute sécurité, peu importe ce qui nécessite un IList.

L'objectif est maintenant de sérialiser / désérialiser cet objet. Cela fonctionne bien avec la sérialisation binaire, mais les objets proxy NHibernate sous-jacents explosent avec des erreurs nhibernate lorsque je tente de les désérialiser.

J'ai donc essayé la sérialisation XML. La sérialisation fonctionne bien et me donne mes belles définitions de classes concrètes dans le fichier XML sérialisé qui supprime complètement les proxys nhibernate. Toutefois, lors de la tentative de désérialisation, il est impossible d'ajouter les éléments à la liste en tant qu'appel items.AsEnumerable.ToList ne permet pas aux éléments d'être ajoutés à la liste sous-jacente via la méthode .Add.

Quelqu'un a-t-il des idées à ce sujet? Est-ce que je m'y prends mal?

** EDIT: La classe de béton NHibernate est NHibernate.Collection.Generic.PersistentGenericBag qui implémente bien IList directement. Cependant, j'ai perdu tous les avantages de la liste générique liés à la sécurité du type. Cela me ramène à devoir écrire un wrapper pour chaque objet enfant et je voulais vraiment éviter cela si possible.

Était-ce utile?

La solution

L'option On consiste à créer votre propre implémentation CustomList qui enveloppe une instance implémentant IList

i.e:

public CustomList<AnotherObject> Items    
{      
    return new CustomList<AnotherObject>(items); 
}

i.e. Lorsque vous ajoutez à votre CustomList < T > , il s’ajoute à la liste de sauvegarde.

Cela semble être le cas tant que votre classe implémentera IList ainsi que IList < T > , tout ira bien.

Autres conseils

Oui, malheureusement, vous ne pouvez pas vous y prendre de cette façon. L'appel de ToList () crée une nouvelle instance de la liste. Ainsi, lorsque vous ajoutez des éléments à cette instance, ils ne seront pas reflétés dans la liste d'origine (comme vous l'avez clairement découvert).

Je n'utilise pas NHibernate, mais je serais curieux de savoir si votre conteneur implémente IList (la version non générique). D'après le fil de discussion que vous avez référencé, il apparaît que System.Collections.IList est ce qui est réellement requis (et qu'il est implémenté par List < T > , c'est pourquoi cela fonctionne). Votre conteneur implémente-t-il IList ?

Ne pouvez-vous pas le lancer comme ça?

public class MyObject
{
    private IList<AnotherObject> items;
    public List<AnotherObject> Items()
    {
        return (List<AnotherObject>)items;
    }
}

Je n'ai pas eu la chance de l'essayer, mais je pense que ça devrait marcher!

Je pense que la collection NHibernate PersistentBag (non générique) implémente IList afin que vous puissiez taper des éléments sous la forme IList au lieu de IList < AnotherObject > . Le lien dans votre question indique que le problème est que le réplicateur a besoin d'un IList que List < T > n'implémente pas, mais IList < T > ne le fait pas (voir figure).

Peut-il être converti en IEnumerable < T > ;? Vous pouvez essayer ceci:

public class MyObject
{
    private IList<AnotherObject> items;
    public List<AnotherObject> Items
    {
        return new List<AnotherObject>items.Cast<AnotherObject>());
    }
    // or, to prevent modifying the list
    public IEnumerable<AnotherObject> Items
    {
        return items.Cast<AnotherObject>();
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top