J'ai une classe à laquelle je suis constamment à ajouter. Il m'est apparu que cette classe n'est pas ouverte-fermée, à cause de l'ajout de toutes ces nouvelles fonctionnalités. J'ai donc pensé à fermer cette classe contre ce changement en encapsulant ces fonctions dans les objets Request. Je me retrouve avec quelque chose comme:Faire une classe suivre OCP - Fonctions Affacturage en objets
public abstract class RequestBase{}
public class AddRequest : RequestBase{}
etc...
public class OrderRepository{
public void ProcessRequest(RequestBase request){}
}
Ce qui rend OrderRepository ouvert pour l'extension et fermé pour modification. Cependant, je suis tombé rapidement en quelques problèmes avec cela:
1.) Les données de la demande qui doit fonctionner sur est à la fois fourni par l'utilisateur (exécution) et l'injection fourni par la dépendance. Je ne peux évidemment pas satisfaire les deux avec un constructeur. Je ne peux pas faire:
public class AddRequest{
public AddRequest(IEnumerable<Order> orders, int UserSuppliedContextArg1, DependencyInjectionArg1, DependencyInjectionArg2);
}
et appeler cela. Je voudrais un moyen pour le cadre DI de construire "partiellement" un objet pour moi, et laissez-moi faire le reste. Je ne vois aucun moyen de le faire cependant. J'ai vu un blog qui appelait ce concept "injection de constructeur variable".
2.) La prochaine chose que je pensais était de diviser cela en 2 classes séparées. L'utilisateur de créer et remplir un RequestContext, puis passer que dans le référentiel, ce qui créerait un RequestProcessor (ne peut pas penser à un meilleur nom) hors de celui-ci. J'ai pensé à faire:
public abstract class RequestContextBase<T> where T : RequestProcessorBase{}
public class AddRequestContext : RequestContextBase<AddRequestProcessor>
public class OrderRepository{
public void ProcessRequest<T>(RequestBase<T> request){
var requestProcessor = IoC.Create<T>();
}
}
et c'était un bon premier pas. Cependant, le processeur de requêtes a besoin du type exact de contexte qu'il stocke, ce que je n'ai pas ici. Je pourrais utiliser un dictionnaire de types de types, mais les défaites dans le but d'être ouvert-fermé .Donc je finis par avoir à faire quelque chose comme:
public class RequestProcessorBase<TRequestContext, TRequestProcessorBase> where TRequestContext : RequestContextBase<TRequestProcessorBase>
C'est bizarre et je suis généralement pas friands de la curiously recurring template pattern. De plus, l'idée que l'utilisateur remplisse un contexte et me demande d'en faire la demande me semble étrange, bien que cela puisse être juste un problème de dénomination.
3.) Je pensais à se débarrasser de tous les ci-dessus et juste avoir:
public AddRequest{
public AddRequest(DependencyInjectionArg1, DependencyInjectionArg2, ...){}
public void PackArgs(UserSuppliedContextArg1, UserSuppliedContextArg2, UserSuppliedContextArg3, ...){}
}
qui est pas mal, mais l'API est laid. Maintenant, les clients de cet objet doivent le «construire» deux fois, pour ainsi dire. Et s'ils oublient d'appeler PackArgs, je dois lancer une exception quelconque.
Je pourrais continuer, mais ce sont les questions les plus confuses que j'ai en ce moment. Des idées?
Cela semble plutôt utile, mais ma question concerne davantage l'encapsulation de requêtes, pas de requêtes. En outre, je n'accède pas à une base de données derrière le référentiel, même si cela ne devrait probablement pas avoir d'importance. – DavidN