2010-12-07 7 views
3

J'ai la configuration suivante avec des constructeurs surchargés que j'ai du mal à trouver une bonne solution. Je ne vois pas comment utiliser une affectation intermédiaire avec un chaînage de constructeur.Construire le chaînage avec des variables intermédiaires

Ce qui suit est pas valide, mais montre ce que je veux faire

public MyThing(IServiceLocator services, int? userId) 
{ 
    // blah.... 
} 

public MyThing(IServiceLocator services, string userName) 
{ 
    User user = services.UserService.GetUserByName(userName); 
    int userId = user == null ? null : (int?)user.Id; 
    // call the other constructor 
    this(services, userId); 
} 

La seule façon que je sais écrire ce qui précède dans le code valide est

public MyThing(IServiceLocator services, string userName) 
    : this(services, 
      services.UserService.GetUserByName(userName) == null ? 
       null : (int?)services.UserService.GetUserByName(userName).Id) 

qui est non seulement le code laid , mais nécessite également l'appel à la base de données deux fois (à moins que le compilateur soit assez intelligent pour travailler sur ce que je doute).

Existe-t-il une meilleure façon d'écrire ce qui précède?

+0

Si ça fait mal, ne le faites pas :-) – VVS

Répondre

1

Il y a, oui. Je sais que le example est en Java mais c'est une si bonne solution à votre problème qu'un effort de portage vers C# a du sens.

2

Qu'en est-ce:

public MyThing(IServiceLocator services, string userName) 
{ 
    User user = services.UserService.GetUserByName(userName); 
    int? userId = user == null ? null : (int?)user.Id; 

    Initialize(services, userId); 
} 


public MyThing(IServiceLocator services, int? userId) 
{ 
    Initialize(services, userId); 
} 

private void Initialize(IServiceLocator services, int? userId) 
{ 
    // initialization logic 
} 

EDIT

Si je vous, je aurait remplacer constructeur avec la méthode d'usine comme ceci:

private MyThing(IServiceLocator services, int? userId) 
{ 
    // blah.... 
} 

public static Create(IServiceLocator services, int? userId) 
{ 
    return new MyThing(services, userId); 
} 

public static Create(IServiceLocator services, string userName) 
{ 
    User user = services.UserService.GetUserByName(userName); 
    int userId = user == null ? null : (int?)user.Id; 

    return new MyThing(services, userId); 
} 

Utilisation:

var myThing = MyThing.Create(services, 123); 
var myOtherThing = MyThing.Create(services, "userName"); 

Replace Constructor with Factory Method (refactoring.com)

+0

Cela fonctionne assez bien pour mon exemple. Si vous commencez à ajouter plus de constructeurs, vous finirez avec beaucoup de code dupliqué (c'est-à-dire si vous voulez en réalité des chaînes de plus de 2 constructeurs). – fearofawhackplanet

+0

+1 Si le constructeur se complique, utilisez une logique d'initialisation séparée. – VVS

+0

@fearofawhackplanet, pouvez-vous donner un exemple de situation avec beaucoup de code dupliqué? – bniwredyc

1

Vous pouvez utiliser une méthode d'assistance statique:

public MyThing(IServiceLocator services, int? userId) 
{ 
    // blah.... 
} 

public MyThing(IServiceLocator services, string userName) 
    : this(services, GetUserId(services, userName)) 
{ 
} 

private static int? GetUserId(IServiceLocator services, string userName) 
{ 
    User user = services.UserService.GetUserByName(userName); 
    return (user == null) ? (int?)null : user.Id; 
} 
Questions connexes