Реализация IErrorHandler с использованием атрибутов уровня класса в WCF
Не повезло с тем, чтобы он работал через конфигурационные файлы, поэтому решил попробовать более надежный способ его настройки с помощью атрибутов уровня класса. Если я смогу заставить это работать, то это, несомненно, отличный способ обернуть исключения в Неисправностях на уровне сервиса без трепетания большого количества кода.
Однако, кажется, что код в атрибуте никогда не запускается - несмотря на код, который определяет атрибут, компилирующийся отлично и распознаваемый IDE. У меня закончились вещи, которые нужно прочитать, чтобы решить эту проблему - исключение, которое нужно обработать, и которое просто бросают.
Я также позаимствовал и вырубил фрагмент кода, найденный на CodePlex, который находится на сайте rorys, чтобы упростить его для этой проблемы без изменения его функции (устранены избыточные перегрузки)
это сводит меня с ума... пожалуйста, помогите!:D
Рори Примула - атрибут реализации
Первоцвет Рори - 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;
}
}
1 ответ
Здесь вам очень трудно помочь, потому что вы не предоставили никакой информации о том, что происходит в вашем приложении.
- Почему это не работает?
- Что происходит (ожидаемое против фактического поведения / результатов)?
- Какие исключения вы получаете на своем клиенте?
- У вас есть настроенная трассировка?
- Есть ли что-нибудь в журнале событий
- Какой у вас сценарий размещения WCF (winforms, windows service, IIS, casini)?
- Вы установили точки останова в обработчике ошибок?
- Как выглядит ваш код?
- Как выглядит ваш конфиг?