我有一个使用 HTTP 协议托管在 IIS7 中的简单 WCF 服务。该服务包含一个方法,该方法返回一个名为 的自定义对象Calendar
。这个对象是非常基本的,并且包含简单的值类型属性,除了一个属性,Holidays
,它的类型是List<IHoliday>
。Holiday
又是一个仅由值类型属性组成的简单类型。
该Calendar
对象从 WCF 服务方法返回到 MVC 控制器,并应用于相应的视图。在使用 dotTrace 进行内存测试期间,很明显 Calendar 对象已由 GC 完成,但有趣的Holidays
是,它的空属性仍保留在堆上。
这不是主要的性能问题,仅占用 32 个字节,但我很想知道为什么没有处理空列表。如有必要,我可以提供代码示例。
源代码和服务配置如下:
public class Calendar : ICalendar
{
[DataMember] private IEnumerable<IHoliday> holidays = new List<IHoliday>();
[DataMember] private IEnumerable<IHolidayNotTaken> holidaysNotTaken = new List<IHolidayNotTaken>();
[DataMember] private IEnumerable<INonInstructionalDay> nonInstructionalDays = new List<INonInstructionalDay>();
[DataMember] private IEnumerable<ISchoolBreak> schoolBreaks = new List<ISchoolBreak>();
}
public class Holiday : IHoliday, IIdentifiable, IDisposable
{
[DataMember(Name = @"date")] [JsonProperty(PropertyName = @"date")] private string date;
[DataMember(Name = @"checked")]
[JsonProperty(PropertyName = @"checked")]
public bool Checked { get; set; }
/// <summary>
/// Gets or sets the end Holiday Id.
/// </summary>
/// <value> The holiday id. </value>
[DataMember(Name = @"id")]
[JsonProperty(PropertyName = @"id")]
public int HolidayId { get; set; }
/// <summary>
/// Gets or sets the end description for the holiday.
/// </summary>
/// <value> The description. </value>
[DataMember(Name = @"description")]
[JsonProperty(PropertyName = @"description")]
public string Description { get; set; }
/// <summary>
/// Gets or sets the date of the holiday.
/// </summary>
/// <value> The holiday date. </value>
[DataMember]
[JsonIgnore]
public DateTime Date { get; set; }
/// <summary>
/// Gets or sets the sort order for the holiday.
/// </summary>
/// <value> The sort order. </value>
[DataMember(Name = @"sortOrder")]
[JsonProperty(PropertyName = @"sortOrder")]
public int SortOrder { get; set; }
/// <summary>
/// Gets the <see cref="IIdentifiable.Type" /> of this instance.
/// </summary>
[DataMember(Name = @"type")]
[JsonProperty(PropertyName = @"type")]
public string Type { get; private set; }
/// <summary>
/// Invoked when this instance is serialising.
/// </summary>
/// <param name="streamingContext"> The streaming context. </param>
[OnSerializing]
private void OnSerialising(StreamingContext streamingContext)
{
date = Date.ToString(@"yyyy-MM-dd");
Type = GetType().ToString();
}
}
服务方式:
public Domain.Calendar GetCalendarByMember(string externalId)
{
try
{
using (var e = new EPlannerEntities())
{
var memberId = e.Members
.Where(m => m.ExternalId == externalId)
.Select(m => m.MemberId)
.SingleOrDefault();
if (memberId.Equals(0))
{
e.Members.AddObject(new Member { ExternalId = externalId.Trim() });
var calendar = new Domain.Calendar
{
DefaultViewId = 2,
MemberId = memberId,
IsWeekendsVisible = true,
TimeFormatId = 1,
DayBeginTime = new TimeSpan(0, 8, 0, 0),
DayEndTime = new TimeSpan(0, 16, 0, 0),
DateFormatId = 1
};
e.Calendars.AddObject(calendar);
e.SaveChanges();
return calendar;
}
return e.Calendars.Single(c => c.MemberId == memberId);
}
}
catch (Exception exception)
{
throw ErrorManager.FaultException(ExceptionType.Business, (int) CalendarErrorCodes.GeneralError, exception);
}
}
服务配置:
<services>
<service behaviorConfiguration="CalendarServiceBehavior" name="HMH.ePlanner.Services.Calendar">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="TCPBinding" name="TCPEndPoint" contract="HMH.ePlanner.Services.ICalendar">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="HTTPBinding" name="HttpEndPoint" contract="HMH.ePlanner.Services.ICalendar" />
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" name="TCPMexEndPoint" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:808/Calendar.svc" />
</baseAddresses>
</host>
</service>
</services>