我有一個WCF服務,託管在IIS中。該服務由通用接口定義,其接口類型爲參數或返回類型,因此我們使用ServiceKnownType屬性在運行時定義所述接口的可用實現。運行一段時間(或IIS應用程序池回收?)後,與ServiceKnownType相關的WCF CommunicationException?
這一切似乎工作正常,但有時,我們看到所有這些服務的請求失敗與CommunicationException;而試圖序列參數http://tempuri.org/「時出錯:ARG設置InnerException消息是‘類型’MyNamespace.SomeInterfaceImplementation‘數據合同名稱’SomeInterfaceImplementation:HTTP://schemas.datacontract.org/2004/07/MyNamespace',不需要將任何靜態未知類型添加到已知類型列表中 - 例如,使用KnownTypeAttribute屬性或將它們添加到傳遞給DataContractSerializer的已知類型列表中。 。「
我無法可靠地重現此錯誤,但它經常在服務運行一段時間(例如;週末)後出現。我最初推測這是由於IIS應用程序池回收而發生的,但是手動回收或小間隔(例如2分鐘)的計劃回收無法重現此問題。
我能夠從「ServiceKnownTypes」的供應商排除「MyNamespace.MyType」可靠地再現異常,但並沒有真正告訴我這是爲什麼擺在首位間歇性的。
以下代碼片段顯示服務聲明。它是針對不同實施類型的通用服務,其中。請注意,它是產生CommunicationException的操作參數'arg'。
[ServiceKnownType("GetKnownTypes", typeof(KnownTypesCache))]
[ServiceContract]
public interface IMyService<T>
where T : class, IMyServiceTypeInterface
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
MyReturnType HandleRequest(T element, ISomeInterfaceArgumentType arg);
}
現在,KnownTypesCache,它提供了已知類型的用於ISomeInterfaceArgumentType的實現是像這樣;
public static class KnownTypesCache
{
private static readonly List<Assembly> queriedAssemblies = new List<Assembly>();
private static readonly List<Type> knownTypes = new List<Type>();
static KnownTypesCache()
{
// get all available assemblies at this time
List<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
// find all available known types publishers
IEnumerable<Type> knownTypesPublisherTypes = assemblies
.Where(a => !queriedAssemblies.Contains(a)) // exclude already queried assemblies to speed things up
.SelectMany(s => s.GetTypes())
.Where(p => typeof(IKnownTypesPublisher).IsAssignableFrom(p) && p.HasAttribute(typeof(KnownTypesPublisherAttribute)));
// add all known types
foreach (Type type in knownTypesPublisherTypes)
{
IKnownTypesPublisher publisher = (IKnownTypesPublisher)Activator.CreateInstance(type);
AddRange(publisher.GetKnownTypes());
}
}
// record the assemblies we've already loaded to avoid relookup
queriedAssemblies.AddRange(assemblies);
}
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
return knownTypes;
}
}
基本上,這個全局靜態緩存查詢中的AppDomain所有加載的組件關於「IKnownTypesPublisher」,這反過來提供可用的序列類型的每個組件的實現者。因此,每個程序集都有一個IKnownTypesPublisher,它只負責識別該程序集中的類型,而KnownTypesCache只是將所有這些信息聚合在一起,並在運行時返回到DataContractSerializer。
正如我所提到的,這種方法似乎在99%的時間內正常工作。然後我無法識別的原因,它停止工作,只能通過致電iisreset解決。
現在我非常難過,我嘗試了各種解決方案,但是因爲我只能等到第一件事星期一才能可靠地再現這個錯誤,這有點難!
我最後剩下的想法是靜態KnownTypesCache構造函數可能在所有程序集加載到AppDomain之前調用,因此緩存在實例的生命週期中將爲空...?