繁体   English   中英

返回语句后的C#fire事件

[英]C# fire event after return statement

我有一个Log方法,它创建一个LogMessage对象,并触发一个事件OnMessage

在调用event后,该方法返回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() ,但我不认为这是一个很好的解决方案。

Task.Delay(1000).ContinueWith(_ => {
    OnMessage?.Invoke(this, new LogMessageCreatedEventArgs { LogMessage = logMessage });
});

return message;

使用Task.Delay(1000)创建竞争条件。 延迟事件直到return不足,因为调用者可能有或没有足够的时间来及时完成对LogMessage修改,以便事件获取修改后的属性。

在触发事件之前确保修改已结束的一种方法是在创建事件和触发事件之间插入一段代码。 这可以通过代表来完成:

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;
}

现在,您可以将预处理逻辑添加到Logger以对LogMessage进行修改:

Logger.Preprocessor = lm => {
    lm.PropertyToBeChanged = newPropertyValue;
    lm.AnotherProperty = someOtherValue;
    return lm;
};

我需要在“上下文”级别更新属性,而不是在全局级别更新属性,在这里我丢失了创建日志消息的位置的信息。

您可以将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