2010-02-21 4 views
3

Je suis en train de concevoir un petit moteur de synchronisation d'annuaires qui peut prendre différents types de sources et gérer la synchronisation incrémentielle. J'ai défini une interface pour un DirectorySource qui ressemble actuellement à ceci:Modèle de conception pour les appels sensibles aux commandes

public interface IDirectorySource 
{ 
    IEnumerable<IDirectoryEntry> GetChanges(IList<string> attributes, IChangeToken token); 
} 

Je ne veux fournir un recenseur au lieu d'une liste afin d'être en mesure d'éviter l'allocation de mémoire inutile, mais mon problème est que je aussi voulez renvoyer un nouvel IChangeToken qui contient les nouvelles informations d'état nécessaires pour l'appel suivant à GetChanges (pour effectuer des mises à jour incrémentielles). Le changetoken doit être calculé après l'énumération est terminée puisque quelqu'un d'autre pourrait mettre à jour le répertoire entre différents appels. J'ai pensé à avoir un deuxième paramètre IChangeToken qui reçoit le nouveau jeton, mais cela ne me semble pas très agréable (et ne serait pas cohérent puisque le jeton serait retourné immédiatement mais ne pourrait pas être rempli tant que l'énumération ne sera pas terminé) .. Et j'ai pensé à retourner quelque chose comme une interface "IChangeSet" qui contient une méthode GetEnumerator et une méthode GetToken, mais le problème est toujours que les appels suivants à la méthode enumerator retourne des données différentes (et ont donc différentes changetokens).

Comment puis-je concevoir une interface qui rend "impossible" à un utilisateur de mon interface de l'utiliser incorrectement concernant mon énumérateur GetChanges et de récupérer le ChangeToken associé?

J'espère que ma question est logique ...;) .. J'ai eu du mal à comprendre ce titre à utiliser pour ma question ...;)

+0

@Per: dans ce cas, vous aimeriez obtenir le même ordre d'idées, et dans lequel un autre un? – Vlad

+0

Le jeton n'est (presque) jamais le même entre différents appels à GetChanges. Il est toujours calculé lorsque vous obtenez les modifications en cours depuis le dernier appel de synchronisation à GetChanges.Dans mes deux actuelles DirectorySource-implementationstests le jeton peut être un cookie de byte-array à partir d'un appel "DirSync" ou de la valeur usnChanged d'un contrôleur de domaine (en fait c'est un horodatage). Je ne sais pas si cette réponse a du sens? ;) – Per

Répondre

1

Dans les langages de programmation fonctionnelle, il est une structure appelée Tuple . Ici, je crois que Tuple est le meilleur choix - tuple, par design, signifie qu'il n'y a pas de relations entre ses éléments. La version actuelle de .NET Framework (3.5) ne prend pas en charge les tuples, mais le suivant (4.0). Si nécessaire, vous pouvez toujours implémenter Tuple par vous-même - pas grave. Malheureusement, C# manque de support de langage pour les tuples, mais F #, par exemple, l'a.

Donc, pour résumer, faire votre interface comme ceci:

Tuple<IEnumerable<IDirectoryEntry>, IChangeToken> GetChanges(IList<string> attributes, IChangeToken token); 
+0

Oui cela fonctionnerait en effet même si un "foreach" -call sur le résultat pourrait être un peu maladroit. Mais j'ai un autre problème (je vais mettre à jour ma question) et c'est que le changetoken n'est disponible qu'après le dénombrement. – Per

+0

Vous pouvez implémenter une relation entre deux éléments dans le tuple - si le client essaie d'appeler une méthode de l'IChangeToken avant l'énumération - lancer une exception. Puisqu'il existe une relation, même cachée, la structure de tuple n'est plus appropriée. –

+1

Dans votre contrat, vous voulez que les clients suivent un comportement strict et complexe. Les méthodes de votre interface doivent être appelées dans un ordre strict, cela ressemble à un état. Peut-être, vous devriez retourner un objet complexe qui maintiendrait l'état et cacherait tous les comportements de sous-liste des clients. –

0

J'ai essayé une approche à l'aide I était « IChangeSet » penser à ma question initiale. Dans ce scénario l'interface IDirectorySource ressemble à ceci:

public interface IDirectorySource 
{ 
    IChangeSet GetChanges(IList<string> attributes, IChangeToken token); 
} 

et mis en œuvre une IChangeSet interface qui ressemble à ceci:

public interface IChangeSet : IEnumerable<IDirectoryEntry> 
{ 
    IChangeToken GetToken(); 
} 

Cela permet d'écrire du code client qui ressemble à ceci:

IChangeSet result = source.GetChanges(attributes, token); 

foreach (IDirectoryEntry entry in result) { 
    // Do something with the data... 
} 

IChangeToken resultToken = result.GetToken(); 

Même si elle permet d'appeler le « GetToken() » - méthode avant l'énumération (ce qui serait mal) je pourrais retourner l'ancien jeton si la fonction est appelé avant que l'énumération soit terminée.

ne se sent pas à 100%, mais il est le meilleur que je peux trouver à ce moment ...

+0

Hmm .. Je réalise maintenant que cela ne change pas beaucoup de mon original. Il ne fait que connecter un peu plus l'énumérateur et le jeton, mais permet toujours plusieurs appels à l'énumérateur, puis l'appel GetToken peut être "désynchronisé". – Per

Questions connexes