-
Notifications
You must be signed in to change notification settings - Fork 1
Home
My collection of many small useful code-snippet .NET, wrapping in reusable library with unobtrusive dependencies. Some of the most-used library are published on nuget
This sample demonstrates How usefull ToolsPack.Net
is.
Here is some brief introduction code. Navigate to the code and unit test samples for more information.
- No dependencies
- Use to display some C# object.
- Know to convert a IEnummerable to string in order do display in a log message
var arr = new string[1000] {"item1".."item1000"};
arr.Display().SeparatedBy("; ").MaxItems(4)
gives
{ item1; item2; item3; item4; ..and 996 (of 1000) more }
- If some items in the array are very long. We should limit the length of individual item with
MaxItemLength()
so that long items will be displayed with...
ellipsis
var arr = new string[1000] {"Lorem ipsum kidda foom", "item2".."item1000"};
arr.Display().MaxItems(4).MaxItemLength(10)
gives
{ [[Lorem...]], item2, item3, item4, ..and 996 (of 1000) more }
- Fast performance it only iterate neccessary items once (complexity O(N))
- see more functionalities in code and test
convert Stopwatch
to string
Stopwatch sw;
Console.WriteLine(sw.DisplayMili()); //get the display string in mili seconds "103 ms"
Console.WriteLine(sw.DisplayMicro()); //get the display string in micro seconds "103,000 mcs"
Console.WriteLine(sw.Display()); //automaticly choose a time unit (day, hour, minute, seconde..) to display
For some serializable object which don't implement ToString(). Newtonsoft.Json can convert them to json. DO NOT use this technique on production. The reflection is bad for Perf..
Newtonsoft.Json.JsonConvert.SerializeObject(someObject);
ArrayDisplayer.DefaultEllipsis("1234567890", 4, "..."); //gives "1234..."
ArrayDisplayer.WordEllipsis("123 567 90", 5, "..."); //gives "123 567..."
In a Unit test project, or a temporary console application, you donnot have to configure the log4net.config any more.
Call
Log4NetQuickSetup.SetUpConsole();
or
Log4NetQuickSetup.SetUpFile("my_small_app.log");
it will setup a typical log4net appender so that you can use them in your test application. Example:
[TestClass]
public class ArrayDisplayerTests
{
private static readonly ILog Log = LogManager.GetLogger(typeof (ArrayDisplayerTests));
[ClassInitialize]
public static void SetUp(TestContext testContext)
{
Log4NetQuickSetup.SetUpConsole();
//or Log4NetQuickSetup.SetUpFile("mytest.log");
}
[TestMethod]
public void DisplayTest()
{
Log.Info("it will display to the Console");
//or to the file if you use SetUpFile()
}
}
See also code-snippet to quickly configure log4net in a C# project
use it to read app.config
Example app.config
of your application
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="connectionString" value="Server=localhost;Database=foo"/>
<add key="activePingService" value="true"/>
<add key="pollIteration" value="100"/>
</appSettings>
</configuration>
You can read these value in your C# application
ConfigReader.Read<string>("connectionString", "a default value if config not found");
ConfigReader.Read<bool>("activePingService", false);
ConfigReader.Read<int>("pollIteration", -1);
Micro-benchmark a part of code to investigate on performance
class MyCalculator
{
private static readonly ILog Log = LogManager.GetLogger(typeof(MyCalculator));
public void Process()
{
using (var etw = ElapsedTimeWatcher.Create(Log, "blockCodeName"))
{
...
etw.Info("step 1");
...
etw.Debug("step 2");
...
etw.Info("Step 3)");
...
} //"sum up log" is displayed here
}
}
- The
etw
wrap the usual loggerLog
, we useetw
to log message instead of the usualLog
- the
blockCodeName
is repeated in the start of each log message, so that we can filter log message by "blockCodeName" - Each log message will display the elapsed time (in micro-second) since the last log message.
- A sum up log will display the total elapsed time (in micro-second) when the
etw
object is disposed.
22:56:59,866 [DEBUG] Begin blockCodeName
22:56:59,970 [INFO ] blockCodeName - 102350 mcs - step 1
22:57:00,144 [DEBUG] blockCodeName - 173295 mcs - step 2
22:57:00,259 [INFO ] blockCodeName - 114036 mcs - Step 3)
22:57:00,452 [INFO ] End blockCodeName : Total elapsed 585436 mcs
var etw = ElapsedTimeWatcher.Create(Log, "checkIntraday").InfoEnd().AutoJump(150, 250).AutoJumpLastLog(500, 1000)
- The log level will auto jump to INFO if the elapsed time exceeds 150 ms
- The log level will auto jump to WARN if the elapsed time exceeds 250 ms
- The above sum up log will switch to INFO if the total elapsed time exceeds 500 ms
- The above sum up log will switch to WARN if the total elapsed time exceeds 1 sec
var etw = ElapsedTimeWatcher.Create(Log, "foo", "Start_context", "End_context");
will give
22:56:59,866 [DEBUG] Begin Start_context
22:56:59,970 [INFO ] foo - 102350 mcs - step 1
22:57:00,144 [DEBUG] foo - 173295 mcs - step 2
22:57:00,259 [INFO ] foo - 114036 mcs - Step 3)
22:57:00,452 [INFO ] End End_context : Total elapsed 585436 mcs
We often display the parameter of the functions in the "Start context". Example:
public void process(string val, bool useCache)
{
var context = string.Format("process(val={0}, useCache={1})", val, useCache);
using (var etw = ElapsedTimeWatcher.Create(Log, "process", context))
{
...
etw.Info("step 1");
...
etw.DebugFormat("step 2");
...
etw.Info("Step 3)");
...
} //"sum up log" is displayed here
}
will give
22:56:59,866 [DEBUG] Begin process(val=Lorem ipsum, useCache=true)
22:56:59,970 [INFO ] process - 102350 mcs - step 1
22:57:00,144 [DEBUG] process - 173295 mcs - step 2
22:57:00,259 [INFO ] process - 114036 mcs - Step 3)
22:57:00,452 [INFO ] End process(val=Lorem ipsum, useCache=true) : Total elapsed 585436 mcs
Avoid redundancy of pure ADO.NET code
- http://www.blackbeltcoder.com/Articles/ado/an-ado-net-sql-helper-class
- I've made an improvement so that we can declare the length of VarChar parameters. It is recommended to always declare length of the VarChar parameters
- http://stackoverflow.com/a/18551053/347051
string qry = "SELECT.. FROM.. WHERE ArtApproved = @Approved AND ArtUpdated > @Updated AND name <> @Foo";
using (AdoHelper db = new AdoHelper(connectionString))
{
using (SqlDataReader rdr = db.ExecDataReader(qry,
"@Approved", true,
"@Foo", "Bazz", 50 //50 is the parameter length to optimize query cache in some case
"@Fuu", "Beuh", //also a varchar parameter, but I do not declare the length (not recommended)
"@Holly", null, //will be replaced by DBNull value
"@Updated", new DateTime(2011, 3, 1)))
{
while (rdr.Read())
{
rdr.GetValue<int?>("views"); //no need to check null value anymore
rdr.GetValue<DateTime?>("lastModified");
}
}
}
https://github.com/Haacked/TimedLock
using(TimedLock.Lock(obj, TimeSpan.FromSeconds(10)))
{
//Thread safe operations
}
- The "synchronized code" will wait for other lock on
obj
free. -
TimeOutException
if the lock acquiring is longer than 10 sec
static readonly NamedLocker<string> CustomerLocker = new NamedLocker<string>();
customerLocker.RunWithLock("Peter.Buy", () =>
{
//synchronized code
}
- The "synchronized code" will wait for other "Peter.Buy"` key free.
static readonly MultiNamedTimedLocker<string> CustomerLocker = new MultiNamedTimedLocker<string>();
using (customerLocker.Lock(new[] {"peter", "david"}, 100))
{
//synchronized code
}
- The "synchronized code" will wait until the
"peter"
and"david"
key of theCustomerLocker
object are free. - After 100 mili-second of waiting:
TimeOutException