7
votes

Comment puis-je abandonner une initialisation d'objet?

J'écris un objet qui doit toujours avoir certaines valeurs. Plus notablement, il doit toujours avoir une valeur pour Nom code> Propriété.

    public User(string name, IQueryable<User> allUsers)
    {
        var matches = allUsers.Where(q => q.Name == name).ToList();
        if(matches.Any())
        {
            // abort object initialization
        }
        Name = name;
    }


5 commentaires

une manière de force brute, définissez tous les champs à NULL, ajoutez l'objet avec des champs NULL, supprimez l'objet.


Cela peut simplement être un code d'échantillon, mais au cas où le cas échéant: vous pouvez fournir un prédicat à tout , de sorte que vous n'ayez pas à passer par .


@Brianrasmussen Les deux ont exactement le même résultat. C'est donc une préférence personnelle que vous utilisez. Le appelle de l'autre main empêche tout court-circuit de ne pas évaluer toute la requête.


@Servy: Bien sûr, je ne dis pas qu'il doit utiliser tout , mais c'est une option et si la liste n'est pas nécessaire, c'est plus simple et éventuellement plus rapide aussi.


Merci pour la pointe sur. Nany ()


9 Réponses :


4
votes

Je suppose que vous pouvez vérifier et jeter une exception dans le constructeur ou le poste de nom de l'objet, mais Eeehehhhh qui peut venir avec une foule de problèmes et des préoccupations mixtes. Je dis créer l'objet via une usine qui fait cette chèque et retourne null (ou une exception bien nommée). Ou créer l'objet POCO et effectuez la validation via une classe / méthode distincte.


0 commentaires

2
votes

Vous devez probablement vérifier le nom duplicate avant de créer l'utilisateur.


2 commentaires

Vous pourriez avoir une condition de course.


Vous pouvez toujours obtenir des conditions de course :-)



6
votes

Eh bien, vous venez de lancer une exception. Mais je n'aime pas ce moyen de manipuler ce problème du tout. Au contraire, vous devez créer l'utilisateur via le service et avoir le contrôle de service si le nom est valide ou non.


0 commentaires

2
votes

Personnellement, je gère des chèques de logique avant d'instancier. Par exemple: xxx

Le présertvalidation aurait toutes les vérifications logiques d'entreprise en fonction de vos besoins.


0 commentaires

0
votes

Ce que vous recherchez est le carte d'identité modèle, ou une sorte de ceci. Il est probablement faux de laisser cette responsabilité dans l'objet lui-même, cela devrait être fait dans la composante créant les entités. Bien sûr, la carte Shaoul soit un fil de sécurité si nécessaire, pour éviter les conditions de course.


0 commentaires

0
votes

Je gérerais cela dans la validation d'avoir l'utilisateur dans la collection. Par exemple, si vous éditez une collection d'utilisateurs, puis de les persister à la base de données, la couche de persistance serait responsable de la validation. J'ai toujours considéré que la mauvaise pratique d'avoir un objet est responsable du maintien de tous les autres objets comme celui-ci. Il introduit une relation d'enfant parent avec l'objet lui-même quand il n'y en a pas. Je suggère de mettre en œuvre un moteur de validation de certaines sortes pour gérer cela.


0 commentaires

3
votes

Au lieu d'avoir un constructeur public, j'ai une méthode comme celle-ci et un constructeur privé: xxx

alors votre code d'appel pourrait utiliser utilisateur myuser = user.createuser ("Steve" ); et gérer le retour nul / exception en conséquence.

On vaut la peine d'ajouter que la méthode que vous utilisez ces magasins que les noms d'utilisateur sont pris, devraient être mis à jour pour dire que ce nom est pris dans le CRÉCOUSER méthode. Sinon, si vous attendez un moment avant de stocker cet objet dans une base de données ou quelque chose, vous aurez toujours des problèmes. J'ai mis à jour le code ci-dessus pour rendre cela plus clair.


2 commentaires

De cette façon, vous pouvez utiliser un iQuéryable pour contenir tous les utilisateurs (ou une référence à un référentiel à tous les utilisateurs) et éviter les conditions de course avec le verrouillage.


@Sweko à la fois cette méthode et l'utilisation d'un constructeur comporte des conditions de course s'il n'y a pas de serrures, et les deux peuvent retirer les conditions de course en ajoutant les verrous appropriés.



0
votes

Au lieu de faire cette validation à l'intérieur de l'objet lui-même, mettez la création, la validation et la sauvegarde de cette entité dans un service. Ce service peut lancer un validationException lorsque le nom d'utilisateur n'est pas unique et pourrait même commencer une transaction pour s'assurer qu'aucune condition de course ne peut se produire. Un bon modèle que j'utilise est le Commande / gestionnaire modèle. Voici un exemple: xxx

vous pouvez même plus la validation dans sa propre classe.


0 commentaires

3
votes

Abandonner l'initialisation d'un objet est effectué en lançant une exception dans le constructeur et est recommandé de rejeter une entrée non valide.

public class User
{
    public User(String name) {
        if (String.IsNullOrWhiteSpace(name)) {
            if (name == null) {
                throw new System.ArgumentNullException("Cannot be null.", "name");
            }
            else {
                throw new System.ArgumentException("Cannot be empty.", "name");
            }
        }
    }
}

public class SomeDataSource {
    public void AddUser(User user) {
        // Do your business validation here, and either throw or possibly return a value
        // If business rules pass, then add the user
        Users.Add(user);
    }
}


1 commentaires

Merci beaucoup pour une réponse aussi détaillée! J'ai été persuadé d'aller de la route de modèle d'usine que vous avez décrite.