Ceci est une solution à ma propre question. Je dois admettre qu'il n'est pas clair dès le début ce que j'essayais d'accomplir, ce qui est évident dans le montage du message initial. Le premier exemple de code est une réponse à une question similaire postée par quelqu'un d'autre sur ce site. Il est très général dans la nature, cependant vous pouvez voir clairement que cette personne essaie de défendre qu'il est possible d'enchaîner les méthodes en retournant le même type d'objet. Je voulais accomplir quelque chose de similaire après avoir regardé le tutoriel intitulé «Rendre votre code C# plus orienté objet» de Zoran Horvat. Ce tutoriel est disponible sur Pluralsight. Son exemple utilise des interfaces et des méthodes d'extension dans les chapitres 4 et 5. L'idée de cette solution est quelque peu similaire, mais je voulais que cette fonctionnalité soit contenue dans une seule classe.
Je pense que toute la confusion est liée au type de l'objet que la méthode doit retourner afin de fournir une fonctionnalité de chaînage. Jetons un coup d'oeil à un exemple de chaîne simple
someString.ToUpper.ToLower.Trim
La première chose qui vient à l'esprit est que la chaîne est passée d'une méthode à une autre méthode et à chaque étape, elle est modifiée par cette méthode. Par conséquent, nous aurions une situation similaire lorsque vous travaillez avec des collections.
movies.GetByYear (1999) .GetByGroup (1) .GetByGenre ("Action")
Dans ce cas, nous commençons par une liste qui est passé à travers cette chaîne de méthodes. Il est également très probable que nous pensons que toutes les méthodes de cette chaîne fonctionnent sur la même liste. Après tout, la propriété de chaîne de l'exemple précédent est partagée par toutes les méthodes même si elle est en cours de modification. Ce n'est pas ce qui se passe réellement avec cette collection de films. Chaque méthode fonctionne avec une collection de taille différente. Il semble que GetByYear() et GetByGroup() sont des méthodes qui fonctionnent avec la même liste de films, ce sont en fait des objets Library séparés qui ont des listes complètement différentes.
Je voudrais remercier Sokohavi qui a laissé des commentaires sur le retour de l'objet Library. Il suggère également de créer l'objet Bibliothèque IEnumerable. Malheureusement, si vous pensez que cette méthode devrait retourner IEnumerable, alors vous êtes sur le mauvais chemin. Techniquement parlant, Library est une liste, mais la liste qui contient les objets Movie est définie sur private et n'est pas visible pour les autres objets. Par conséquent, il n'y a rien à parcourir. L'objet Bibliothèque n'a que des méthodes de couplage, et si vous en sélectionnez un, vous perdrez l'accès aux autres méthodes de la même classe. Par conséquent, la méthode doit renvoyer l'objet Library afin d'accéder à toutes les méthodes de la même classe, et la liste qui stocke l'objet Movie doit être IEnumerable. Il y a un inconvénient à cette approche. Vous ne pouvez pas charger de données dans cette liste à l'intérieur du constructeur de la bibliothèque. Au lieu de cela, les données sont passées en paramètre. Maintenant, vous avez des objets qui ont différentes listes de films et la façon dont ils communiquent entre eux est à travers leurs constructeurs. Ci-dessous nous avons la classe Repository qui charge des éléments individuels dans une liste à travers son constructeur. La classe Library définit des méthodes qui fourniront un filtrage de la liste qui lui est transmise. Vous pouvez également créer une autre couche d'abstraction qui utiliserait cette fonctionnalité.
public class Movie
{
public string Title { get; set; }
public int Year { get; set; }
public int GroupId { get; set; }
public string Genre { get; set; }
}
public class Repository
{
private List<Movie> localDb;
public Repository()
{
localDb = new List<Movie>();
}
public IEnumerable<Movie> GetAllMovies()
{
localDb = new List<Movie>();
var movie1 = new Movie() { Title = "Movie1", Year = 2000, GroupId = 1, Genre = "Action" };
var movie2 = new Movie() { Title = "Movie2", Year = 1999, GroupId = 1, Genre = "Drama" };
var movie3 = new Movie() { Title = "Movie3", Year = 2000, GroupId = 1, Genre = "Comedy" };
var movie4 = new Movie() { Title = "Movie4", Year = 2000, GroupId = 2, Genre = "Action" };
var movie5 = new Movie() { Title = "Movie5", Year = 1999, GroupId = 2, Genre = "Drama" };
var movie6 = new Movie() { Title = "Movie6", Year = 1999, GroupId = 2, Genre = "Drama" };
var movie7 = new Movie() { Title = "Movie7", Year = 1999, GroupId = 2, Genre = "Horror" };
localDb.Add(movie1);
localDb.Add(movie2);
localDb.Add(movie3);
localDb.Add(movie4);
localDb.Add(movie5);
localDb.Add(movie6);
localDb.Add(movie7);
return localDb;
}
}
public class Library
{
private IEnumerable<Movie> MoviesLibrary;
public Library(IEnumerable<Movie> movies)
{
this.MoviesLibrary = movies.ToList();
}
public Library GetByYear(int year)
{
return new Library(this.MoviesLibrary.Where(movie => movie.Year == year));
}
public Library GetById(int id)
{
return new Library(this.MoviesLibrary.Where(movie => movie.GroupId == id));
}
public IEnumerable<Movie> GetByGenre(string genre)
{
return this.MoviesLibrary.Where(movie => movie.Genre == genre);
}
public void Display()
{
foreach (var movie in this.MoviesLibrary)
{
Console.WriteLine("Title: {0} , Year {1}, Group: {2}, Genre: {3}", movie.Title,movie.Year,movie.GroupId, movie.Genre);
}
}
}
Comment utiliser ces classes:
var repository = new Repository();
var listOfMovies = repository.GetAllMovies();
var movies = new Library(listOfMovies);
var selectedMovies1 = movies.GetByYear(2000).GetById(1).GetByGenre("Action");
var selectedMovies2 = movies.GetByYear(2000).GetById(2);
foreach (var movie in selectedMovies1)
{
Console.WriteLine("Selected 1 - Title: {0} , Year {1}, Group: {2}, Genre: {3}", movie.Title,movie.Year,movie.GroupId, movie.Genre);
}
selectedMovies2.Display();
Sortie:
choisi 1 - Titre: Film1, Année 2000, Groupe: 1, Genre: Action
Titre: MOVIE4 , Année 2000, Groupe: 2, Genre: Action
Comprenez-vous ce que ['this'] (https://msdn.microsoft.com/fr-fr/library/dk1507sz.a spx) est? –
Question est très confuse, mais il semble que vous voulez "méthode chaining" - http://stackoverflow.com/questions/1119799/method-chaining-in-c-sharp –
J'ai édité mon message initial – tipitoe