我正在编写一个使用Exchange Web服务处理电子邮件附件的应用程序。
我的问题区域的一般结构如下:
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;
}
起初,这看起来还不错 - 它完美地处理了我之前的测试示例。但是当我开始使用批量加载进行测试时,我意识到它只处理前10个项目,因为我指定的批量大小为10个项目(ItemView view = new ItemView(10
)),但我没有检查更多批次。
我可以简单地增加批量大小,但稍后快速谷歌,我找到了一个更好的例子:
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;
}
这会循环播放尽可能多的电子邮件,但由于我无法理解的原因,foreach循环现在只处理findResults中的第一项。
即使findResults包含多个项目(findResults.Items.Count
&gt; 1),我的第二个示例findResults.MoreAvailable
= false。很公平,我早先已经完成了批量操作,所以我看到最后一批的结尾是有道理的。
但是如何重置findResults以便它将处理整个批次?我尝试设置findResults.MoreAvailable但它只是readonly ...我错过了什么?
结论:
好的,所以我可以一次处理一个项目,或者我可以将每个批次中的每个项目添加到List中,然后像我现在一样处理它们。
他们之间没有太多关系;我最初开始使用List,但我会进一步考虑这个选择。
答案 0 :(得分:8)
在我看来,你的主要问题是你尝试定义一个返回FindItemsResults<Item>
的函数。如果使用配对结果,您将拥有此类型的不是一个对象。而不是在检索每个新页面时,FindItemsResults<Item>
将被覆盖。以下示例显示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);
代码显示控制台输出上的主题。如果您想以其他方式使用EmailMessage
或MeetingRequest
,则应修改代码对应方。您还可以定义一个委托,该委托对找到的EmailMessage
或MeetingRequest
执行某些操作,并在Console.WriteLine
的位置调用该委托。如果你确实需要在某个地方使用相同的所有项目,那么你必须创建一些像List<Item>
这样的集合,填写函数并返回而不是你当前所做的FindItemsResults<Item>
。