Skip to content

Instantly share code, notes, and snippets.

@llaughlin
Last active April 8, 2019 13:47
Show Gist options
  • Save llaughlin/6112dde3b6a6b4ba8545faf960923b95 to your computer and use it in GitHub Desktop.
Save llaughlin/6112dde3b6a6b4ba8545faf960923b95 to your computer and use it in GitHub Desktop.
dotnet Extensions

Collection of extensions and code fragments.

public static class Log4Net2Serilog
{
/// <summary>
/// Configures log4net to log to Serilog.
/// </summary>
/// <param name="logger">The serilog logger (if left null Log.Logger will be used).</param>
public static void Configure(ILogger logger = null)
{
var serilogAppender = new SerilogAppender(logger);
serilogAppender.ActivateOptions();
var loggerRepository = (Hierarchy)LogManager.GetRepository(Assembly.GetCallingAssembly());
if (loggerRepository.Root.GetAppender(serilogAppender.Name) == null)
{
loggerRepository.Root.AddAppender(serilogAppender);
}
loggerRepository.Configured = true;
}
private class SerilogAppender : AppenderSkeleton
{
private static readonly Func<SystemStringFormat, string> FormatGetter;
private static readonly Func<SystemStringFormat, object[]> ArgumentsGetter;
private readonly ILogger _Logger;
static SerilogAppender()
{
FormatGetter = GetFieldAccessor<SystemStringFormat, string>("m_format");
ArgumentsGetter = GetFieldAccessor<SystemStringFormat, object[]>("m_args");
}
public SerilogAppender(ILogger logger = null) => _Logger = logger;
protected override void Append(LoggingEvent loggingEvent)
{
var source = loggingEvent.LoggerName;
var serilogLevel = ConvertLevel(loggingEvent.Level);
string template;
object[] parameters = null;
if (loggingEvent.MessageObject is SystemStringFormat systemStringFormat)
{
template = FormatGetter(systemStringFormat);
parameters = ArgumentsGetter(systemStringFormat);
}
else
{
template = loggingEvent.MessageObject?.ToString();
}
var logger = (_Logger ?? Log.Logger).ForContext(Constants.SourceContextPropertyName, source);
logger.Write(serilogLevel, loggingEvent.ExceptionObject, template, parameters);
}
private static LogEventLevel ConvertLevel(Level log4NetLevel)
{
if (log4NetLevel == Level.Verbose)
{
return LogEventLevel.Verbose;
}
if (log4NetLevel == Level.Debug)
{
return LogEventLevel.Debug;
}
if (log4NetLevel == Level.Info)
{
return LogEventLevel.Information;
}
if (log4NetLevel == Level.Warn)
{
return LogEventLevel.Warning;
}
if (log4NetLevel == Level.Error)
{
return LogEventLevel.Error;
}
if (log4NetLevel == Level.Fatal)
{
return LogEventLevel.Fatal;
}
SelfLog.WriteLine("Unexpected log4net logging level ({0}) logging as Information", log4NetLevel.DisplayName);
return LogEventLevel.Information;
}
//taken from http://rogeralsing.com/2008/02/26/linq-expressions-access-private-fields/
public static Func<T, TField> GetFieldAccessor<T, TField>(string fieldName)
{
var param = Expression.Parameter(typeof(T), "arg");
var member = Expression.Field(param, fieldName);
var lambda = Expression.Lambda(typeof(Func<T, TField>), member, param);
var compiled = (Func<T, TField>)lambda.Compile();
return compiled;
}
}
}
public static class MemoryExtensions
{
private static readonly List<string> ByteNames = new List<string> {"Bytes", "KB", "MB", "GB"};
public static string ToFileSize(this int source) => Convert.ToInt64(source).ToFileSize();
public static string ToFileSize(this long source)
{
const int byteConversion = 1024;
var bytes = Math.Abs(Convert.ToDouble(source));
var prefix = source < 0 ? "-" : "";
for (var i = 4; i >= 0; i--)
{
var converted = Math.Pow(byteConversion, i);
if (bytes >= converted)
{
return $"{prefix}{Math.Round(bytes / converted, 2)} {ByteNames[i]}";
}
}
return "Unknown";
}
}
public static class ObservableExtensions
{
public static IObservable<IList<T>> SlidingWindow<T>(this IObservable<T> source, int windowSize)
{
var publishedSource = source.Publish().RefCount();
return Enumerable.Range(0, windowSize)
.Select(skip => publishedSource.Skip(skip)).Zip();
}
}
public static class SlidingWindowExtensions
{
public static IObservable<IList<T>> SlidingWindow<T>(this IObservable<T> source, int windowSize)
{
var publishedSource = source.Publish().RefCount();
return Enumerable.Range(0, windowSize)
.Select(skip => publishedSource.Skip(skip)).Zip();
}
public static IEnumerable<IList<T>> SlidingWindow<T>(this IEnumerable<T> source, int windowSize)
{
var window = new List<T>(windowSize);
foreach(var line in source)
{
if(window.Count == windowSize)
{
window.RemoveAt(0);
}
window.Add(line);
if(window.Count == windowSize)
{
yield return window;
}
}
//return Enumerable.Range(0, source.Count()).Select(i => source.Skip(i).Take(windowSize).ToList());
}
}
<Target Name="NugetRestore" BeforeTargets="Build" Condition=" !Exists('obj\project.assets.json') ">
<Message Importance="high" Text="Restoring nuget packages..." />
<Exec Command="nuget restore" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="nuget restore failed" />
</Target>
<Target Name="YarnRestore" BeforeTargets="Build">
<Exec Command="yarn --version" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="yarn is required to build and run this project." />
<Message Importance="high" Text="Restoring yarn packages..." />
<Exec Command="yarn" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="error running yarn" />
</Target>
<Target Name="DebugRunWebpack" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' ">
<!-- Ensure Node.js is installed -->
<Exec Command="node --version" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
<!-- In development, the dist files won't exist on the first run or when cloning to
a different machine, so rebuild them if not already present. -->
<Message Importance="high" Text="Performing first-run Webpack build..." />
<Exec Command="node node_modules/webpack/bin/webpack.js --config webpack.config.js" />
<Exec Command="node node_modules/webpack/bin/webpack.js" />
</Target>
<Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
<!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
<Exec Command="node node_modules/webpack/bin/webpack.js --config webpack.config.js --env.prod" />
<Exec Command="node node_modules/webpack/bin/webpack.js --env.prod" />
<!-- Include the newly-built files in the publish output -->
<ItemGroup>
<DistFiles Include="wwwroot\dist\**" />
<ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
<RelativePath>%(DistFiles.Identity)</RelativePath>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</ResolvedFileToPublish>
</ItemGroup>
</Target>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment