返回语句后的C#fire事件
我有一个返回语句后的C#fire事件,c#,asp.net,C#,Asp.net,我有一个Log方法,它创建一个LogMessage对象,并触发一个事件OnMessage 调用事件后,该方法返回LogMessage对象 是否可以延迟事件,使其发生在return语句之后 我之所以需要它,是因为我希望能够在事件引发之前更改LogMessage对象 public class Logger { public static event LogMessageCreatedEventHandler OnMessage; public LogMessage Log(stri
Log
方法,它创建一个LogMessage
对象,并触发一个事件OnMessage
调用事件
后,该方法返回LogMessage
对象
是否可以延迟事件,使其发生在return语句之后
我之所以需要它,是因为我希望能够在事件引发之前更改LogMessage
对象
public class Logger
{
public static event LogMessageCreatedEventHandler OnMessage;
public LogMessage Log(string logLevel, string message)
{
LogMessage logMessage = new LogMessage
{
Message = message,
LogLevel = logLevel,
DateTime = DateTime.UtcNow
};
OnMessage?.Invoke(this, new LogMessageCreatedEventArgs { LogMessage = logMessage });
return logMessage;
}
}
// usage
var logMessage = _logger.Log("Debug", "Product has been created"); <-- the event is invoked now
logMessage.CustomProp.Add("isProductsService", true); <-- this property is not available in the Event Handler
使用Task.Delay(1000)
创建竞争条件。将事件延迟到返回之后
是不够的,因为调用者可能没有足够的时间完成对日志消息的修改,也可能没有足够的时间让事件拾取修改后的属性
确保在触发事件之前完成修改的一种方法是在创建事件和触发事件之间插入一段代码。这可以通过委托完成:
public static event LogMessageCreatedEventHandler OnMessage;
// By default message preprocessor does nothing
public static Func<LogMessage,LogMessage> Preprocess { get; set; } = m => m;
public LogMessage Log(string logLevel, string message) {
LogMessage logMessage = new LogMessage {
Message = message,
LogLevel = logLevel,
DateTime = DateTime.UtcNow
};
OnMessage?.Invoke(this, new LogMessageCreatedEventArgs {
LogMessage = Preprocess(logMessage)
});
return logMessage;
}
我需要在“上下文”级别更新属性,而不是在全局级别,在全局级别上,我会丢失创建日志消息的位置的信息
您可以将Func
作为参数传递给Log
,如下所示:
private static readonly Func<LogMessage,LogMessage> doNothing = m => m;
public LogMessage Log(string logLevel, string message, Func<LogMessage,LogMessage> preprocess = doNothing) {
LogMessage logMessage = new LogMessage {
Message = message,
LogLevel = logLevel,
DateTime = DateTime.UtcNow
};
OnMessage?.Invoke(this, new LogMessageCreatedEventArgs {
LogMessage = preprocess(logMessage)
});
return logMessage;
}
private static readonly Func doNothing=m=>m;
公共日志消息日志(字符串日志级别、字符串消息、Func预处理=doNothing){
LogMessage LogMessage=新日志消息{
消息=消息,
LogLevel=LogLevel,
DateTime=DateTime.UtcNow
};
OnMessage?.Invoke(这是新的LogMessageCreatedEventArgs{
LogMessage=预处理(LogMessage)
});
返回日志消息;
}
这是一个非常奇怪的解决方案。如果需要更改LogMessage
,请返回副本。如果需要向消息中添加其他属性,只需添加方法重写即可将其包含在原始Log()调用中。是否从事件处理程序返回副本?不,事件处理程序需要具有更新属性alreadyPass'Action'回调的“最终”版本才能记录,以便调用方可以在触发事件之前应用所需的修改。公认的答案类似但不相同-我建议使用本地回调,而不是全局回调。感谢您提供的解决方案。虽然这样做有效,但这不是理想的方法,因为我需要在“上下文”级别更新属性,而不是在全局级别更新属性,在全局级别上,我会丢失创建日志消息的位置的信息。这并没有回答问题,但似乎这是唯一可靠的解决方案。非常感谢。
Logger.Preprocessor = lm => {
lm.PropertyToBeChanged = newPropertyValue;
lm.AnotherProperty = someOtherValue;
return lm;
};
private static readonly Func<LogMessage,LogMessage> doNothing = m => m;
public LogMessage Log(string logLevel, string message, Func<LogMessage,LogMessage> preprocess = doNothing) {
LogMessage logMessage = new LogMessage {
Message = message,
LogLevel = logLevel,
DateTime = DateTime.UtcNow
};
OnMessage?.Invoke(this, new LogMessageCreatedEventArgs {
LogMessage = preprocess(logMessage)
});
return logMessage;
}