[英]C# fire event after return statement
I have a Log
method which creates a LogMessage
object, and fires an event OnMessage
我有一个Log
方法,它创建一个LogMessage
对象,并触发一个事件OnMessage
The method returns the LogMessage
object after the event
has been invoked. 在调用event
后,该方法返回LogMessage
对象。
Is it possible to delay the event, so it occurs after the return statement? 是否有可能延迟事件,所以它发生在return语句之后?
The reason i need this, is because i want to be able to alter the LogMessage
object before the event will raise. 我需要这个的原因是因为我希望能够在事件提升之前改变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
One idea would be to use Task.Delay()
, but i don't think this is a good solution. 一个想法是使用Task.Delay()
,但我不认为这是一个很好的解决方案。
Task.Delay(1000).ContinueWith(_ => {
OnMessage?.Invoke(this, new LogMessageCreatedEventArgs { LogMessage = logMessage });
});
return message;
Using Task.Delay(1000)
creates a race condition. 使用Task.Delay(1000)
创建竞争条件。 Delaying the event till after the return
is insufficient, because the caller may or may not have enough time to complete its modifications to LogMessage
in time for the event to pick up modified properties. 延迟事件直到return
不足,因为调用者可能有或没有足够的时间来及时完成对LogMessage
修改,以便事件获取修改后的属性。
One way to make sure that modifications are over before the event is fired is to plug a piece of code in between of creating the event and firing it. 在触发事件之前确保修改已结束的一种方法是在创建事件和触发事件之间插入一段代码。 This can be done with a delegate: 这可以通过代表来完成:
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;
}
Now you can add preprocessing logic to Logger
to make modifications to LogMessage
: 现在,您可以将预处理逻辑添加到Logger
以对LogMessage
进行修改:
Logger.Preprocessor = lm => {
lm.PropertyToBeChanged = newPropertyValue;
lm.AnotherProperty = someOtherValue;
return lm;
};
I need to update the property at "contextual" level, rather than on Global level, where I lose the information from where the log message was created. 我需要在“上下文”级别更新属性,而不是在全局级别更新属性,在这里我丢失了创建日志消息的位置的信息。
You can pass the Func
as a parameter to Log
, as follows: 您可以将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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.