Execute custom business logic
XData has many features targeting this technology as not only ORM, but a full featured Data Access Layer. This is one of this features.
Custom logic defined as public property of XDataLogic<T> class descendant with type of CustomLogic<T>.
public class InvoiceLogic : XDataLogic<Invoice>
{
public CustomLogic<Invoice> TestCustomLogic => (objects => {
Log.Write(MessageType.Information,
() => $"TestCustomLogic called with {objects.Length} objects");
foreach (var invoice in objects)
{
var i = invoice;
invoice.PostData("testPost",
() => Encoding.UTF8.GetBytes(i.DocNumb));
var p = Encoding.UTF8.GetBytes(i.DocNumb);
var r = i.Callback("testCall", ref p);
Log.Write(MessageType.Information, () =>
@$"Call for \"{i.DocNumb}\" returned \"{r}\"
with data \"{(p == null ? null : Encoding.UTF8.GetString(p))}\"");
}
return true;
});
}
...
//Call example logic
var random = new Random();
return dataScope.GetRepository<Invoice>().ToArray().Execute(() => "TestCustomLogic",
"testPost".SetValue((Action<byte[]>)(data =>
Console.WriteLine("Post message received (data=\"{0}\")",
data == null ? null : Encoding.UTF8.GetString(data))))
.AsEnum().ToDictionary(),
"testCall".SetValue((Func<byte[], byte[]>)(data => {
Console.WriteLine("Call received \"{0}\")",
data == null ? null : Encoding.UTF8.GetString(data));
return random.NextDouble() >= 0.5 ? null : Encoding.UTF8.GetBytes(
$"reply for \"{(data == null ? null : Encoding.UTF8.GetString(data))}\"");
})).AsEnum().ToDictionary());
Programmer can develop data centric logic over some of mapped objects with ability to execute this logic in the middle ware layer of three-tier architecture on a dedicated server (or cluster). And this code can be simple and representable debugged in two-tier environment. Architecture can be switched by configuration! No code modification, no side effects... This feature is linked with Trigger logic and reached by Callbacks.
When code is organized using data mapping modules, data logic modules and client (or Web site) it can help programmer to keep module relations clean and get ready to changes, with no matter of middle-ware layer existence. And this rules are not dictated, You can use it or not. You can write this logic anywhere You architect to do. Nothing will be breaks, except of ability to use XData three-tier architecture. But if You really don't need it, what is wrong?