... skipping 1000 words about bad solutions ...
The Clean/Best Solution
Here's a pattern that elegantly handles this situation:
public void RefreshGrid()
{
// 1. Store the current entity before refresh
SomeEntity currentEntity = null;
if (dataGrid.ActiveRow != null)
{
currentEntity = dataGrid.ActiveRow.ListObject as SomeEntity;
}
// 2. Refresh the grid
dataGrid.RefreshData();
// 3. Restore selection using entity ID
if (currentEntity != null)
{
dataGrid.ActiveRow = dataGrid.Rows.FirstOrDefault(r =>
((SomeEntity)r.ListObject).Id == currentEntity.Id);
}
}
Why This Pattern Is Best Practice
- Type Safety: Using the strongly-typed entity object instead of raw values
- Identity-Based: Uses unique IDs instead of volatile row positions
- Null-Safe: Handles cases where no row is selected
- Concise: LINQ makes the code readable and maintainable
- Reliable: Works even if data order changes or rows are filtered
安子 尽量多发现身边那些笑点很低,很容易满足,无论何时看起来都是喜洋洋的人,并且尽量多的跟他们在一起,你会感觉到被滋养,被激发,被启迪。它们像炭火一样煲养你的生命,给你力量,带来喜悦,他们是真正的人间天使。(更重要的,只要你贴他们足够近,他们还有能力把你转化成他们的同类)
碧螺姑娘 突然间真实感受到了“人生是旷野”的具体意义。虽然风刀霜剑严相催,但就是要热热闹闹地去活着。
奧匈帝國小説家弗朗茨·卡夫卡(Franz Kafka)寫過一則微型小説叫《法律門前》。小説講的是:有個鄉下人走到一處敞開的大門前,但是看門人不讓他進去。鄉下人問,那他以後可不可以進去呢?看門人跟他説,以後有可能,但是現在不行。看門人還暗示他說,如果他實在想進去,可以試一試,不過裏面還有更多看門人守著其他大門,這些看門人一個比一個難纏。後來這個鄉下人就在這個大門前等了一輩子,就等有機會允許他進去。等到自己快要死的時候,鄉下人問:爲什麽一直沒有其他人要求進這個大門?看門人跟他說:因爲這個大門就是專門給你一個人開的,等你死了,大門就會關起來。
人生若梦为欢几何 有句话说的很好,你把生活当游戏,把周围所有的人当npc,就不会内耗了。
CarrieZ 人类之所以进步,是因为下一代不听上一代的话。
…more
Wen working with QuickFix/n ibrary , efficient logging is crucial for troubleshooting. Here's how to implement a custom logging solution that routes QuickFix logs through NLog to your ELK stack.
Key Components
- NLogAdapter: A custom adapter that implements QuickFix's
ILog
interface:
public class NLogAdapter(ILogger logger) : ILog
{
private const string HeartbeatPattern = @"\x0135=0\x01";
private static readonly Regex HeartbeatRegex = new(HeartbeatPattern, RegexOptions.Compiled);
private static bool IsHeartBeat(string message) => HeartbeatRegex.IsMatch(message);
public void OnIncoming(string message)
{
if (!IsHeartBeat(message))
{
logger.Info("Incoming: {Message}", message);
}
}
// ... other implementations
}
- NLogQuickFixLogFactory: A factory class to create log instances:
public class NLogQuickFixLogFactory(ILog logger) : ILogFactory
{
public ILog Create(SessionID sessionId) => logger;
public ILog CreateNonSessionLog() => logger;
}
Implementation Steps
- Register Dependencies in your DI container:
builder.Services.AddSingleton<NLog.ILogger>(_ => LogManager.GetCurrentClassLogger());
builder.Services.AddSingleton<ILog, NLogAdapter>();
builder.Services.AddSingleton<ILogFactory, NLogQuickFixLogFactory>();
- Configure QuickFix to use the custom logger:
var initiator = new SocketInitiator(
clientApp,
storeFactory,
sessionSettings,
new NLogQuickFixLogFactory(quickfixLogger) // Use custom logger injeted by ILog here
);
Key Features
- Heartbeat Filtering: Reduces log noise by filtering out FIX heartbeat messages
- Structured Logging: Uses NLog's structured logging format for better parsing in ELK
- Separation of Concerns: Cleanly separates QuickFix logging from application logging
Benefits
- Centralized logging in ELK stack
- Better debugging apabilities
- Reduced log volume through heartbeat filtering
- Consistent logging format across your application
Here’s a consolidated list of common NUnit Assert
statements, categorized by their purpose. This should cover most of the common scenarios:
Basic Assertions
-
Equality:
Assert.That(actual, Is.EqualTo(expected));
Assert.That(actual, Is.Not.EqualTo(expected));
-
Boolean Conditions:
Assert.That(condition, Is.True);
Assert.That(condition, Is.False);
-
Null Checks:
Assert.That(obj, Is.Null);
Assert.That(obj, Is.Not.Null);
String Assertions
-
Contains:
Assert.That(actualString, Does.Contain(substring));
-
Starts With / Ends With:
Assert.That(actualString, Does.StartWith(prefix));
Assert.That(actualString, Does.EndWith(suffix));
-
Empty or Not Empty:
Assert.That(actualString, Is.Empty);
Assert.That(actualString, Is.Not.Empty);
-
Matches Regex:
Assert.That(actualString, Does.Match(regexPattern));
Collection Assertions
-
Contains Item:
Assert.That(collection, Does.Contain(item));
-
Has Specific Count:
Assert.That(collection, Has.Count.EqualTo(expectedCount));
-
Empty or Not Empty:
Assert.That(collection, Is.Empty);
Assert.That(collection, Is.Not.Empty);
-
Unique Items:
Assert.That(collection, Is.Unique);
Numeric Assertions
-
Greater Than / Less Than:
Assert.That(actual, Is.GreaterThan(expected));
Assert.That(actual, Is.LessThan(expected));
-
Greater Than or Equal / Less Than or Equal:
Assert.That(actual, Is.GreaterThanOrEqualTo(expected));
Assert.That(actual, Is.LessThanOrEqualTo(expected));
-
In Range:
Assert.That(actual, Is.InRange(lower, upper));
Type Assertions
-
Instance of Type:
Assert.That(obj, Is.TypeOf<ExpectedType>());
Assert.That(obj, Is.InstanceOf<ExpectedType>());
-
Assignable From:
Assert.That(obj, Is.AssignableTo<ExpectedType>());
Exception Assertions
-
Throws Exception:
Assert.Throws<ExpectedExceptionType>(() => { methodCall(); });
-
Throws Specific Exception with Condition:
var ex = Assert.Throws<ExpectedExceptionType>(() => { methodCall(); });
Assert.That(ex.Message, Does.Contain("expected message"));
Miscellaneous
-
Same Instance:
Assert.That(actual, Is.SameAs(expected));
Assert.That(actual, Is.Not.SameAs(expected));
-
Applies a Condition:
Assert.That(collection, Has.Some.Matches<ExpectedType>(item => item.Condition));
-
Delayed Constraints (Asynchronous):
Assert.That(() => condition, Is.True.After(500).PollEvery(50));
-
Group related assertions together to improve readability and reporting:
Assert.Multiple(() =>
{
Assert.That(okResult, Is.Not.Null, "okResult should not be null");
Assert.That(okResult.Value, Is.TypeOf<string>(), "Value should be of type string");
});