简体   繁体   English

返回语句后的C#fire事件

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM