2
通過配置文件無法運行它,所以決定嘗試去通過類級別屬性進行更合理的doign操作。如果我可以得到這個工作,那麼顯然是一種很好的方法,可以在處理服務層的故障時將異常封裝在許多代碼中。在WCF中使用類級別屬性實現IErrorHandler
但是,屬性中的代碼似乎永遠不會運行 - 儘管代碼定義了屬性編譯非常好,並被IDE識別。關於解決這個問題,我已經耗盡了一些東西 - 只是被處理的異常而被拋出。
我也借用和砍下的一段代碼在CodePlex上發現,是rorys網站簡化它對於這個問題,而不改變其功能(除去多餘的過載)
這是推動我瘋了...請幫忙! :d
Rory Primrose - attribute implementation
Rory Primrose - IErrorHandlerImplementation
的代碼:
服務接口和實現
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(FaultException))]
string GetData(int value);
}
[ErrorHandler(typeof(KnownErrorHandler))]
public class Service1 : IService1
{
public string GetData(int value)
{
throw new Exception("This exception should get handled.");
}
}
KnownErrorHandler實現:
public class KnownErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
Trace.WriteLine(error.ToString());
return true;
}
public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
{
FaultException faultException = new FaultException("Server error encountered. All details have been logged.");
MessageFault messageFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, faultException.Action);
}
}
屬性定義 - 懷疑問題在這裏。我相當確定這是我如何使用這段代碼。
[AttributeUsage(AttributeTargets.Class)]
public sealed class ErrorHandler : Attribute, IServiceBehavior
{
public ErrorHandler(Type errorHandler)
{
if (errorHandler == null)
{throw new ArgumentNullException("errorHandler");}
Type[] errorHandlerTypes = new[] { errorHandler };
Initialize(errorHandlerTypes);
}
public void AddBindingParameters(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{
// Nothing to do here
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
if (serviceHostBase == null)
{
throw new ArgumentNullException("serviceHostBase");
}
// Loop through each channel dispatcher
for (Int32 dispatcherIndex = 0; dispatcherIndex < serviceHostBase.ChannelDispatchers.Count; dispatcherIndex++)
{
// Get the dispatcher for this index and cast to the type we are after
ChannelDispatcher dispatcher = (ChannelDispatcher)serviceHostBase.ChannelDispatchers[dispatcherIndex];
// Loop through each error handler
for (Int32 typeIndex = 0; typeIndex < ErrorHandlerTypes.Count; typeIndex++)
{
Type errorHandlerType = ErrorHandlerTypes[typeIndex];
// Create a new error handler instance
IErrorHandler handler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
// Add the handler to the dispatcher
dispatcher.ErrorHandlers.Add(handler);
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{ }
private void Initialize(Type[] errorHandlerTypes)
{
const String ErrorHandlerTypesParameterName = "errorHandlerTypes";
if (errorHandlerTypes == null)
{
throw new ArgumentNullException(ErrorHandlerTypesParameterName);
}
if (errorHandlerTypes.Length == 0)
{
throw new ArgumentOutOfRangeException(ErrorHandlerTypesParameterName);
}
List<String> typeNames = new List<String>(errorHandlerTypes.Length);
// Loop through each item supplied
for (Int32 index = 0; index < errorHandlerTypes.Length; index++)
{
Type errorHandlerType = errorHandlerTypes[index];
// Check if the item supplied is null
if (errorHandlerType == null)
{
throw new ArgumentNullException(ErrorHandlerTypesParameterName);
}
// Check if the type doesn't define the IErrorHandler interface
if (typeof(IErrorHandler).IsAssignableFrom(errorHandlerType) == false)
{
// We can't use this type
throw new InvalidCastException();
}
String assemblyQualifiedName = errorHandlerType.AssemblyQualifiedName;
if (typeNames.Contains(assemblyQualifiedName) == false)
{
typeNames.Add(assemblyQualifiedName);
}
else
{
throw new ArgumentException(
String.Format(CultureInfo.CurrentCulture, "Duplicate ErrorType Provided", assemblyQualifiedName));
}
}
// Store the types
ErrorHandlerTypes = new ReadOnlyCollection<Type>(errorHandlerTypes);
}
/// <summary>
/// Gets the error handler types.
/// </summary>
/// <value>
/// The error handler types.
/// </value>
public ReadOnlyCollection<Type> ErrorHandlerTypes
{
get;
private set;
}
}
原來的代碼工作正常... iis在我工作的計算機上壞了。應該不需要修改網絡配置,因爲這種實現方法應該是完全獨立的。 主機是Windows 7上的IIS,並且主要合約調用之外的斷點都不會被打 - 它們在每個方法條目上。沒有什麼被追查出來......就好像編譯後的代碼不存在 - 屬性標記沒有引起異常並且很高興。 無論如何,你的代碼,我從你的博客發佈,所以我想答案是你的。非常感謝博客文章。 – 2010-07-13 10:36:40
我很高興它爲你工作:) 我發現我需要步入一個WCF客戶端代理呼叫,以便能夠擊中託管服務內的斷點。如果您正在跨過WCF調用或運行沒有客戶端斷點的運行,那麼可能是您遇到的問題。 – 2010-07-14 04:32:24
我與斷點奔跑,並正在進入服務......它真的是二戰變得更加奇怪。我重新安裝了我的機器,它第一次完美運行。 – 2010-07-22 13:48:07