2010-09-30 6 views
3

Je suis en train d'écrire une application pour traiter les pièces jointes à un courrier électronique, à l'aide des services Web Exchange.Services Web Exchange: traitement groupé avec FindItemsResult <Item>

La structure générale de ma problématique est la suivante:

public static void Main() 
{ 
    FindItemsResults<Item> findResults = FindItems(); 

    foreach (Item item in findResults) 
    { 
     DoSomethingWithItem(item); 
    } 
} 

public static FindItemsResults<Item> FindItems() 
{ 
      FindItemsResults<Item> findResults; 

      ItemView view = new ItemView(10); //batching 10 at a time 
      view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Ascending); 
      view.PropertySet = new PropertySet(
       BasePropertySet.IdOnly, 
       ItemSchema.Subject, 
       ItemSchema.DateTimeReceived); 

      findResults = service.FindItems(
       WellKnownFolderName.Inbox, 
       new SearchFilter.SearchFilterCollection(
        LogicalOperator.Or, 
        new SearchFilter.ContainsSubstring(ItemSchema.Subject, Properties.Settings.Default.EmailSubject)), 
       view); 

      //return set of emails 
      return findResults; 
} 

Au début, cela avait l'air correct - il a traité mes exemples d'essais antérieurs parfaitement. Mais quand j'ai commencé à tester avec des charges en vrac, j'ai réalisé qu'il ne traitait que les 10 premiers éléments, puisque je spécifiais une taille de lot de 10 articles (ItemView view = new ItemView(10)), mais je ne vérifiais pas d'autres lots.

je pouvais avoir simplement augmenté la taille du lot, mais un rapide Google plus tard, je trouve un meilleur exemple:

public static FindItemsResults<Item> FindItems() 
{ 
      FindItemsResults<Item> findResults; 

      ItemView view = new ItemView(10, 0, OffsetBasePoint.Beginning); 
      view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Ascending); 
      view.PropertySet = new PropertySet(
       BasePropertySet.IdOnly, 
       ItemSchema.Subject, 
       ItemSchema.DateTimeReceived); 

      do 
      { 
       findResults = service.FindItems(
        WellKnownFolderName.Inbox, 
        new SearchFilter.SearchFilterCollection(
         LogicalOperator.Or, 
         new SearchFilter.ContainsSubstring(ItemSchema.Subject, Properties.Settings.Default.EmailSubject)), 
        view); 

       //any more batches? 
       if (findResults.NextPageOffset.HasValue) 
       { 
        view.Offset = findResults.NextPageOffset.Value; 
       } 
      } 
      while (findResults.MoreAvailable); 

      return findResults; 
} 

Cette boucle à travers autant de courriels que je me soucie de jeter, mais pour des raisons que je ne peut pas encore comprendre, la boucle foreach ne traite maintenant que le premier élément de findResults.

Même si findResults contient plus d'un élément (findResults.Items.Count> 1), avec mon deuxième exemple, findResults.MoreAvailable = false. Assez juste, j'ai bouclé les lots plus tôt, il est donc logique que je regarde la fin du dernier lot.

Mais comment réinitialiser findResults pour traiter tout le lot? J'ai essayé de placer findResults.MoreAvailable mais c'est readonly ... Qu'est-ce que je manque?

CONCLUSION:

OK, donc je peux soit traiter les éléments d'un lot à la fois, ou je peux ajouter chaque élément dans chaque lot à une liste et de les traiter plus tard, comme je le fais actuellement.

Il n'y en a pas beaucoup entre eux; J'ai d'abord commencé à utiliser une liste, mais je vais considérer le choix plus loin.

Répondre

8

Il me semble que votre problème principal est que vous essayez de définir une fonction qui renvoie FindItemsResults<Item>. Si vous utilisez l'association des résultats, vous aurez pas un objet de ce type. Au lieu de cela lors de la récupération de chaque nouvelle page, le FindItemsResults<Item> sera remplacé. Suite à des sujets d'affichage par exemple de tous les éléments du Inbox:

ItemView view = new ItemView(10, 0, OffsetBasePoint.Beginning); 
view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Descending); 
view.PropertySet = new PropertySet(
    BasePropertySet.IdOnly, 
    ItemSchema.Subject, 
    ItemSchema.DateTimeReceived); 

// save the folder where we will make searching to do this one time 
Folder myInbox = Folder.Bind(service, WellKnownFolderName.Inbox); 

FindItemsResults<Item> findResults; 

do 
{ 
    findResults = myInbox.FindItems(
     new SearchFilter.ContainsSubstring(ItemSchema.Subject, 
       Properties.Settings.Default.EmailSubject)), 
     view); 

    foreach (Item item in findResults) 
    { 
     // Do something with the item. 
     Console.WriteLine(); 
     if (item is EmailMessage) 
     { 
      EmailMessage em = item as EmailMessage; 
      Console.WriteLine("Subject: \"{0}\"", em.Subject); 
     } 
     else if (item is MeetingRequest) 
     { 
      MeetingRequest mr = item as MeetingRequest; 
      Console.WriteLine("Subject: \"{0}\"", mr.Subject); 
     } 
     else 
     { 
      // we can handle other item types 
     } 
    } 

    //any more batches? 
    if (findResults.NextPageOffset.HasValue) 
    { 
     view.Offset = findResults.NextPageOffset.Value; 
    } 
} 
while (findResults.MoreAvailable); 

L'affichage du code Les sujets sur la sortie de la console. Si vous souhaitez utiliser EmailMessage ou MeetingRequest d'une autre manière, vous devez modifier le code correspondant. Vous pouvez également définir un délégué qui fait quelque chose avec le EmailMessage trouvé ou MeetingRequest et appelez le délégué sur la place de Console.WriteLine. Si vous avez besoin de tous les éléments quelque part, alors vous devrez créer une collection comme List<Item>, remplir là dans la fonction et retourner au lieu de FindItemsResults<Item> que vous faites actuellement.

Questions connexes