这是旧的,但它仍然出现在搜索中,所以我会尝试改进答案,因为我刚刚在我们公司经历过这个。
正如 Dmitry 所写,重复约会的出现是不存在的,除非并且直到它们成为例外,因为用户在出现时更改了某些内容。这也意味着他们没有独立的ID。
但是,如果没有更改,每个异常都有其发生的原始日期。对于每个非异常事件,该日期只是事件的开始日期。
表示
您可以使用全局约会 id 和原始日期的组合来获取一个唯一标识约会的 ID,即使它是一个事件:
public struct AppointmentId : IEquatable<AppointmentId>
{
private readonly string GlobalAppointmentId;
private readonly LocalDate? OriginalDate;
public AppointmentId(string globalAppointmentId)
{
this.GlobalAppointmentId = globalAppointmentId;
this.OriginalDate = null;
}
public AppointmentId(string globalAppointmentId, LocalDate originalDate)
{
this.GlobalAppointmentId = globalAppointmentId;
this.OriginalDate = originalDate;
}
public bool Equals(AppointmentId other)
{
return this.GlobalAppointmentId.Equals(other.GlobalAppointmentId, StringComparison.Ordinal) &&
this.OriginalDate == other.OriginalDate;
}
public override bool Equals(object obj) =>
obj is AppointmentId other && this.Equals(other);
public override int GetHashCode()
{
unchecked
{
int hash = 62207;
hash += 3 * this.GlobalAppointmentId.GetHashCode();
hash += (5 * this.OriginalDate?.GetHashCode() ?? 0);
return hash;
}
}
public override string ToString()
{
if (this.GlobalAppointmentId == null) return "<None>";
if (this.OriginalDate == null)
{
return $"{this.GlobalAppointmentId}";
}
return $"{OriginalDate.Value)} / {GlobalAppointmentId}";
}
public static bool operator ==(AppointmentId x, AppointmentId y) => x.Equals(y);
public static bool operator !=(AppointmentId x, AppointmentId y) => !(x == y);
}
这里我使用来自 NodaTime 的 LocalDate 来表示没有时间组件的原始日期。
访问
可以轻松访问全局约会 ID。如前所述,并非例外的事件的原始日期只是约会开始的日期部分。
当您只有AppointmentItem 而没有来自RecurrencePattern 的Exception 对象时,例外情况会更加麻烦,因为原始日期不能直接获得。但是你可以通过PropertyAccessor获得它:
public static LocalDate GetOriginalDate(this AppointmentItem appointment)
{
// The original date is stored in a property called ExceptionReplaceTime but this
// property is not exposed in the OOM so we need to use PropertyAccessor
// See: https://docs.microsoft.com/en-us/office/client-developer/outlook/mapi/pidlidexceptionreplacetime-canonical-property
using (var props = appointment.PropertyAccessor.AsOwnedResource())
{
var p = props.Resource.GetProperty("http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/82280040");
DateTime exceptionReplaceTime = (DateTime)p;
return props.Resource.UTCToLocalTime(exceptionReplaceTime).ToLocalDate();
}
}