Здесь у вас есть один подход, использующий redu () и findIndex () для нового массива, который будет объединен. Если новый объект, который должен быть объединен, уже существует (т. Е. Свойство name
соответствует некоторому объекту), мы увеличиваем остальные соответствующие свойства и добавляем несуществующие, в противном случае мы передаем весь новый объект:
[ 117]
const initial = [
{name: 'a', times: 40, other: 50},
{name: 'b', times: 10, other: 15},
{name: 'c', times: 15, other: 12}
];
const toBeMerged = [
{name: 'a', times: 45, other: 30, another: 76},
{name: 'c', times: 10, other: 10},
{name: 'd', times: 23, other: 10}
];
let newArray = toBeMerged.reduce((res, curr) =>
{
let found = res.findIndex(x => x.name === curr.name);
if (found >= 0)
{
res[found] = Object.keys(curr).reduce((r, c) =>
{
r[[c]] = (r[[c]] && c !== 'name') ? r[[c]] + curr[[c]] : curr[[c]];
return r;
}, res[found]);
}
else
{
res.push(curr);
}
return res;
}, initial);
console.log(newArray);
Хорошо, я изучил идею IErrorHandler. Я понятия не имел, что Вы могли сделать это этот путь, и это прекрасно, потому что это позволяет Вам избежать выгод попытки для каждого метода. Можно ли сделать это в стандартных веб-сервисах также? Я реализовал его следующий путь:
/// <summary>
/// Services can intercept errors, perform processing, and affect how errors are reported using the
/// IErrorHandler interface. The interface has two methods that can be implemented: ProvideFault and
/// HandleError. The ProvideFault method allows you to add, modify, or suppress a fault message that
/// is generated in response to an exception. The HandleError method allows error processing to take
/// place in the event of an error and controls whether additional error handling can run.
///
/// To use this class, specify it as the type in the ErrorBehavior attribute constructor.
/// </summary>
public class ServiceErrorHandler : IErrorHandler
{
/// <summary>
/// Default constructor
/// </summary>
public ServiceErrorHandler()
{
}
/// <summary>
/// Specifies a url of the service
/// </summary>
/// <param name="strUrl"></param>
public ServiceErrorHandler(string strUrl, bool bHandled)
{
this.strUrl_m = strUrl;
this.bHandled_m = bHandled;
}
/// <summary>
///HandleError. Log an error, then allow the error to be handled as usual.
///Return true if the error is considered as already handled
/// </summary>
/// <param name="error"></param>
/// <returns></returns>
public virtual bool HandleError(Exception exError)
{
System.Diagnostics.EventLog evt = new System.Diagnostics.EventLog("Application", ".", "My Application");
evt.WriteEntry("Error at " + this.strUrl_m + ":\n" + exError.Message, System.Diagnostics.EventLogEntryType.Error);
return this.bHandled_m;
}
/// <summary>
///Provide a fault. The Message fault parameter can be replaced, or set to
///null to suppress reporting a fault.
/// </summary>
/// <param name="error"></param>
/// <param name="version"></param>
/// <param name="msg"></param>
public virtual void ProvideFault(Exception exError,
System.ServiceModel.Channels.MessageVersion version,
ref System.ServiceModel.Channels.Message msg)
{
//Any custom message here
/*
DataAccessFaultContract dafc = new DataAccessFaultContract(exError.Message);
System.ServiceModel.FaultException fe = new System.ServiceModel.FaultException<DataAccessFaultContract>(dafc);
System.ServiceModel.Channels.MessageFault fault = fe.CreateMessageFault();
string ns = "http://www.example.com/services/FaultContracts/DataAccessFault";
msg = System.ServiceModel.Channels.Message.CreateMessage(version, fault, ns);
*/
}
private string strUrl_m;
/// <summary>
/// Specifies a url of the service, displayed in the error log
/// </summary>
public string Url
{
get
{
return this.strUrl_m;
}
}
private bool bHandled_m;
/// <summary>
/// Determines if the exception should be considered handled
/// </summary>
public bool Handled
{
get
{
return this.bHandled_m;
}
}
}
/// <summary>
/// The ErrorBehaviorAttribute exists as a mechanism to register an error handler with a service.
/// This attribute takes a single type parameter. That type should implement the IErrorHandler
/// interface and should have a public, empty constructor. The attribute then instantiates an
/// instance of that error handler type and installs it into the service. It does this by
/// implementing the IServiceBehavior interface and then using the ApplyDispatchBehavior
/// method to add instances of the error handler to the service.
///
/// To use this class specify the attribute on your service class.
/// </summary>
public class ErrorBehaviorAttribute : Attribute, IServiceBehavior
{
private Type typeErrorHandler_m;
public ErrorBehaviorAttribute(Type typeErrorHandler)
{
this.typeErrorHandler_m = typeErrorHandler;
}
public ErrorBehaviorAttribute(Type typeErrorHandler, string strUrl, bool bHandled)
: this(typeErrorHandler)
{
this.strUrl_m = strUrl;
this.bHandled_m = bHandled;
}
public virtual void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
{
return;
}
public virtual void AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{
return;
}
protected virtual IErrorHandler CreateTypeHandler()
{
IErrorHandler typeErrorHandler;
try
{
typeErrorHandler = (IErrorHandler)Activator.CreateInstance(this.typeErrorHandler_m, this.strUrl_m, bHandled_m);
}
catch (MissingMethodException e)
{
throw new ArgumentException("The ErrorHandler type specified in the ErrorBehaviorAttribute constructor must have a public constructor with string parameter and bool parameter.", e);
}
catch (InvalidCastException e)
{
throw new ArgumentException("The ErrorHandler type specified in the ErrorBehaviorAttribute constructor must implement System.ServiceModel.Dispatcher.IErrorHandler.", e);
}
return typeErrorHandler;
}
public virtual void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
IErrorHandler typeErrorHandler = this.CreateTypeHandler();
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
channelDispatcher.ErrorHandlers.Add(typeErrorHandler);
}
}
private string strUrl_m;
/// <summary>
/// Specifies a url of the service, displayed in the error log
/// </summary>
public string Url
{
get
{
return this.strUrl_m;
}
}
private bool bHandled_m;
/// <summary>
/// Determines if the ServiceErrorHandler will consider the exception handled
/// </summary>
public bool Handled
{
get
{
return this.bHandled_m;
}
}
}
Сервис:
[ServiceContract(Namespace = "http://example.come/test")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ErrorBehavior(typeof(ServiceErrorHandler),"ExceptonTest.svc",false)]
public class ExceptonTest
{
[OperationContract]
public void TestException()
{
throw new Exception("this is a test!");
}
}
Я предложил бы, чтобы Вы для централизации обработки ошибок сервиса WCF вместо помещения пробовали/завоевывали популярность каждый метод. Чтобы сделать это, можно реализовать интерфейс IErrorHandler:
public class ErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
{
DataAccessFaultContract dafc = new DataAccessFaultContract(error.Message);
var fe = new FaultException<DataAccessFaultContract>(dafc);
Message fault = fe.CreateMessageFault();
string ns = "http://www.example.com/services/FaultContracts/DataAccessFault";
msg = Message.CreateMessage(version, fault, ns);
}
}
ProvideFault
метод называют каждый раз, когда один из Вашего OperationContract
выдает исключение. Это преобразует исключение в определенное пользовательское FaultContract
и отправьте его клиенту. Таким образом, Вы больше не должны помещать попытку/выгоду в каждый метод. Можно также отправить другое FaultContract
в зависимости от выданного исключения.
На стороне клиента необходимо поймать FaultException<DataAccessFaultContract>
каждый раз Вы называете метод на своем веб-сервисе.