Root / Assembly / ARCCore / AREnumType / DocumentationOnlyEnum / ARConcepts / _Member

PRich

_Member

KeyValue
AdHocQueryThe concept of a Client doing an ad-hoc query against (normally) a ArmDB.
Background: Ordinarily, Subscription are 'permanently' on-going, and ad-hoc queries are done in-memory locally by each client, but since there is just some small differences conceptually in doing ad-hoc queries over a TCP/IP connection, AgoRapide implements also this mechanism.

AdHocQuery is most relevant against an ArmDB storing its data in a PRich, (The query itself is sent as a collection of Subscription elements, and when server answers with IsAtEndOfStream the client can close the query connection)

TODO: Not implemented as of May 2020.
TODO: Clarify difference between ClientUpdatePosition and FromTime / ToTime.

Note that there would be little meaning in doing an ad-hoc query against a CoreDB because the core only stores single PropertyStream-lines, meaning it would have to read through the whole database from start to end in order to ensure that all data is found (the query would be an O(n) one instead of O(1)).

Hint: If you are concerned about the risk of having to do O(n) queries, you are recommended to use an established key-value storage (like AWS DynamoDB or Azure Cosmos DB) as your main database, and sync AgoRapide to that database.
See ARCSync for more information about this.

TOOD: Could potentially be deleted as ARConcept when a Query-metod is implemented somewhere.

Description, EnumMember, EnumType
AgoRapideHistoryAgoRapide has roots back to 2011 when Bjørn Erling Fløtten invented panSL (SL = Schema language).

Introduced in 2012 panSL (panSL.org) was an excercise in data modelling where the principle of TaggingOfPropertyKeys orginated, in that case, tagging each element of the schema in order to create a data-driven application with only 'one page' of code.
The implementation of panSL was called AgoRapide (AgoRapide.com).
It had litte practical use.

In 2017 a new version of AgoRapide (https://github.com/AgoRapide/AgoRapide), not using panSL at all, was introduced, as a 'Lightweight pragmatic integrated .NET REST API offering JSON and HTML views. Written in C# 7.0'.
This version introduced PropertyAccess and most other ARConcepts.
It was 'halfway' to implementing PropertyStream, in the sense that all data where stored as 'key, value' but was dependent on an underlying storage mechanism, like PostgreSQL.
The 2017 version has had applications within some companies, including a modestly successful IoT related company (Sikom Connect AS of Trondheim, Norway).
Its weaknesses where its monolitic structure and too much emphasis on being a REST API (meaning it was an 'all-or-nothing package', without useful single components).

The current 2020 version of AgoRapide (this version), uses .NET Core and .NET Standard.
It introduces its own storage mechanism (see StreamProcessor).
It consists of multiple mostly independent components (see ARComponents).
It is built outwards from the core component ARCCore.
Each component is kept as simple as possible. ARCCore for instance can be accessed through the concept of a Console application and it does not link to any library outside of Microsoft .NET itself.
(in general the 2020 version of AgoRapide should be ideally suited for containerization).

Description, EnumMember, EnumType
ApplicationSpecificCodeCode specific for an end-application.

Should be kept to a minimum (obviously).

TODO: Consider creating new enum CodeLocation or similar,
TOOD: comprising StandardAgoRapideCode and ApplicationSpecificCode.

Will usually be contained within a Client and some ArmDB.

Through AvoidingRepetition, AgoRapide strives to help you keep your ApplicationSpecificCode to a minimum.

See StandardAgoRapideCode for more information

Description, EnumMember, EnumType, LongDescription
AssertionsAndDetailedExceptionMessagesThe abstraction level in AgoRapide is very high.

This means that if something breaks (either due to a bug in the StandardAgoRapideCode or due to wrong use of the libraries from ApplicationSpecificCode) it can sometimes be difficult to grasp the issue involved.

The StandardAgoRapideCode therefore has lots of assertions (in order to catch the exception at its root origin) and also very detailed exception messages (in order to clarify and educate).


Description, EnumMember, EnumType
AvoidingRepetitionAvoiding repetition, the overarching philosophy that inspired the rest of AgoRapide.

By repetition we mean all kinds of tasks that are similar to each other, both:
1) Within an application and
2) Across different applications.

Some examples of 1) are documentation, logging, debugging and business reporting.
These are actually quite similar problem domains and therefore handled in AgoRapide by a lot of common code.
(see ARCQuery for more information about reports / queries).

Some examples of 2) are creation of database tables, creation of C# objects, implementing properties for objects, populating objects, validating properties (and handling the unknown / null / maybe scenarios), traversing entity relations, creating API-methods (building API endpoints), writing unit tests.
These are quite similar across applications and should not demand much ApplicationSpecificCode

Every time that we developers see such patterns of repetition we try to factor out the common component.
AgoRapide has been created for the purpose of making this process easier.

The advantages of this are self-evident: Less code, less complexity, easier debugging, more meaningful workdays as a programmer and so on and so on.

We do especially want to remove some of the friction resulting when working with a system where you know that some common functionality for dealing with a problem really should have been implemented. But since it was not available from the start it is too time-consuming to implement now, meaning that instead a lot of kludges get scattered all over the code in order to at least cover some emergency needs. It all ends up with an in-overall inefficient and costly to maintain system.

To quote Paul Graham 'The shape of a program should reflect only the problem it needs to solve'
(Paul Graham - Revenge of the Nerds, http://www.paulgraham.com/icad.html ).
By utilizing AgoRapide your application will hopefully accomplish this (but maybe we should have written AgoRapide in Lisp though).

Another quote:
'Fools ignore complexity. Pragmatists suffer it. Some can avoid it. Geniuses remove it.'
(Alan Perlis, Epigrams on Programming, 1982, ACM SIGPLAN Notices #58, https://en.wikiquote.org/wiki/Alan_Perlis#Epigrams_on_Programming,_1982 ).

However, we also have this gem, not to be forgotten:
'Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?'
(Brian Kernighan, The Elements of Programming Style, https://en.wikiquote.org/wiki/Brian_Kernighan ).

AgoRapide's level of abstraction is already close to this territory (about debugging is twice as hard). However, your resulting application will hopefully require much less cleverness thanks to AgoRapide, so at least you can debug your own code very easily (see also AssertionsAndDetailedExceptionMessages).


Description, EnumMember, EnumType, LongDescription
CoreDBSynchronizationTODO: The inherent possibility in AgoRapide of having multiple CoreDB nodes means that synchronization between these nodes must be considered.
As of Apr 2020 the most critical issue being identified is probably how to re-synchronize nodes after some period of offline status / network outage and similar.
Also a mechanism for anointing a master-node and similar must be implemented.

TODO: There is also the issue of what happens when the core itself is unavailable. In principle the clients are perfectly capable of caching data, and sending it as soon as the core gets online again, but then there is the issue of ordering data from the different client nodes correctly into the property stream.
One possible solution to this issue might be to just state that it is unsolved and that such cached data will be put into the property stream without any coordination / ordering.

See also MultipleConnectionUsage and Sharding.

Description, EnumMember, EnumType
DataRetentionThe concept of when to delete old data (if deemed necessary).

Because of inherent traits of the PropertyStream concept, data will never be deleted by default.

This might result in unacceptable storage requirements / low performance. Some functionality for deletion is therefore envisaged to be necessary to implement.
See NoRealDeletion for details.

TODO: Not implemented as of Mar 2020. Not decided if should be in a specific ARComponents or just part of ARCCore.
Will probably be a specific BasePKAttribute called PKRetAttribute, maybe also something added to ClassAttribute (or something added to EnumAttribute. As of Apr 2020 we have not decided where / how to tag 'entity'-classes).
Note that retention at application level is also plausible. One scenario could be a high-availability log-collector delivering log-data to more simple (cheaper) final storage nodes that are not necessarily high-availablity themselves. The log-collector only has to keep data for as long as the final storage nodes are tolerated to be offline.

Description, EnumMember, EnumType, LongDescription
DocumentationThanks to the tagging of enums and classes in AgoRapide (like this description), automatically generation of documentation is possible.
The actual functionality for that is not part of ARCCore but is placed in -ARCDoc.(apart from all the BaseAttribute instances necessary for tagging the different classes and members of course)


Description, EnumMember, EnumType
ExposingApplicationStateThe traditional debugging process usually entails reading through logs and querying about your application state through a debugging tool. AgoRapide encourages logs and application state to be distributed over the PropertyStream by default, thereby making debugging simpler (the information is always available, and not restricted to some local access).

You are encouraged to expose your internal application state to the PropertyStream through the use of classes implementing LogContext (and possible also use PKLogAttribute) like PConcurrent.

This has two implications (as implemented by PConcurrent):
1) Any call to Log / HandleException ends up in the property stream.
2) Any change to internal properties will be reflected in the property stream automatically without even having to make 'manual' calls to Log (because all calls to -SetP- will automatically be logged to the property stream).

Some example classes inheriting PConcurrent and using this principle in AgoRapide are:

StreamProcessor (search for code like 'IP.SetPV(StreamProcessorP.ClientUpdatePositionPath ...)
ActualConnection (search for code like 'IP.Inc(ActualConnectionP.CountReceiveMessage)')

In summary, much of the inner working of these classes are automatically exposed to the property stream without any special code having to be added.
Note how manual calls to Log are also automatically exposed to the property stream in these classes.
Note how threads are always given a descriptive name in these classes, making the logging even easier to follow.

All this makes debugging and understanding the inner workings of your applications much easier reducing the need for external logging and debugging tools.

Note also that by exposing the internal application state to the PropertyStream it can be read 'from' wherever convenient.
In other words, you do not have to limit use of IP to only data-objects like 'Customer', 'Order' and similar, but you can also use it for internal parts of your application

Description, EnumMember, EnumType, LongDescription
GettingStartedAgoRapide 2020 is an open source library for building data-oriented backend applications using .NET Standard 2.1.

The source code, including this documentation, is found at

https://bitbucket.org/BjornErlingFloetten/arcore


AgoRapide 2020 can be used as:

1) A distributed in-memory backend processor of events / listener to events.
The PropertyStream-format lends itself well to distribution of loads. Each processing node subscribes to sub-sets of the entire property stream.
The Subscriptions consists of the events to which the node has to respond, plus other necessary data in order to correctly process the events.
The result is placed back out in the property stream, either back upstream, or further downstream for other nodes to process.
See ARCCore.

2) A 'single-endpoint' API.
All data is exposed through a standardized API query mechanism (REST or GraphQL) with no need for writing application specific endpoints.
Since APIs should expose well defined DTO's and not entire entities, AgoRapide APIs are therefore normally established as separate nodes.
Each node has a well defined Subscription to a sub-set of your entire database (also reducing the memory footprint).
The API will then in effect offer DTO's with very little coding needed.
See ARCAPI.

3) A reporting tool / query tool ("Express BI").
An API as in 2) combined with the query library.
The query library enables report generation directly from the web-browser (as a single bookmark-able URL).
See ARCQuery.

For all cases above the following also applies:

A) An in-memory database which is continously updated through the property stream is provided by AgoRapide.
This ensures short response times and significantly reduces network traffic.
See StreamProcessor.

B) The core database storage is either provided directly by AgoRapide, or you can use an established 'key-value' databases like DynamoDB or Cosmos DB.
See ARCSync.

C) High performance thread-safe "simultaneous" read and writes is supported in all scenarios.

D) AgoRapide works better the more strongly typed schema you specify (see TaggingOfPropertyKeys).
You can however start out without any schema at all. Duck typing is then used instead.
Even relational queries are possible straight out-of-the-box without any schema, as long as some naming conventions are followed
(like Order.CustomerId for instance, in order to relate an Order to a Customer)
Strong typing is used by AgoRapide whenever specified by the schema.

E) Scaling is supported by flexible routing of the PropertyStream to multiple nodes.

F) No dependencies to other libraries apart from .NET itself.

See ARCDoc for practical examples for using AgoRapide.

AgoRapide is the result of a strong wish of AvoidingRepetition.

Three very important concepts in AgoRapide are:

1) PropertyStream: The concept of how all data is broken down into single 'key and value' pairs which are then stored as plain text format lines and then never changed.

2) TaggingOfPropertyKeys: The concept of specifying in a single place all relevant information about a given property (data field).

3) PropertyAccess: The general mechanism for accessing properties of objects in AgoRapide.

AgoRapide is split into different ARComponents. You can have a functional distributed storage mechanism including log-consoles by linking only to ARCCore.
Choose from the other components based on your security needs (ARCSec), the complexity of your data (ARCQuery) or other needs (see ARComponents in general).

See also ARConcepts and AgoRapideHistory.

Description, EnumMember, EnumType
IdLooseStorageAgoRapide does not give a unique identifier to every object / property (due to memory usage concerns). Instead each object / property has an id valid within a limited scope or context described by a collection of IK (as stored inside -Key).

TODO: This enum-member (IdLooseStorage) has marginal value, try to move text elsewhere and delete member.
TODO: Move for instance text to IndividualItems.

TODO: Write something about keys not being stored inside object (CustomerId is not stored inside Customer typically).

Example 1): If the scope is 'Customer' then an id for a specific customer could be '42'
Example 2): If the scope is 'Customer/42' then an id for a PhoneNumber would be either:
a) For storing only single values (see HistoryOnly):
'Customer/42/PhoneNumber = +90534333'
or
b) For storing multiple values (see WholeCollection):'Customer/42/PhoneNumber/+4790534333'
'Customer/42/PhoneNumber/+4740178178'
and so on.


Description, EnumMember, EnumType, LongDescription
LinkInsertionInDocumentationDocumentation with links is much easier to read.

On the other hand, inserting links can often be quite tedious in a typical markup language.

AgoRapide offers a very easy method for link insertion: You just prepend and append the relevant word that you want a link to, with a minus sign / hyphen, '-' in the documentation.

If the relevant word is a C# identifier, you should in addition use the 'nameof' keyword, in order to catch renames and deletions of terms and also in order to be able to easy navigate within your developing environment (like when working within Visual Studio, using F12).

If this is done methodically, then any mechanism for creating for instance HTML documentation, (like the one offered in ARCDoc, that was by the way just an example of linking) can then first identify all terms (or files) that are created, and then blindly replace in the text -[Filename]- with '<a href="[Filename]">[Filename]</a>' without actually knowing anything about the text's structure.

This is a pragmatic approach that works surprisingly well.
See also doc.

Description, EnumMember, EnumType, LongDescription
ManyToManyRelationsARCQuery supports many-to-many relations in a simple manner without introducing a third entity type (a third table).

This is done through having foreign keys with cardinality IsMultiple like WholeCollection and IndividualItems.

Example 1), tagging PersonP.CarId with IndividualItems:
Person/42/CarId/1968
Person/42/CarId/1981
Person/43/CarId/1968

Example 2), tagging PersonP.CarId with WholeCollection:
Person/42/CarId = 1968;1981
Person/43/CarId/1968

In both examples person 42 owns two cars (1968 and 1981), but shares car 1968 with person 43.
(you can of course also store many-to-many relations in the traditional RDBMS manner by using a third 'entity' type called PersonCarOwnership or similar).


Description, EnumMember, EnumType
MemoryConsumptionA naïve implementation of key-value storages like AgoRapide may lead to excessive memory (RAM) consumption.

AgoRapide has been designed in order to be easy to start with, but still with inbuilt flexibility to reduce memory consumption as your database grows and your application matures.

CoreDB will mostly store data on disk and have little need for RAM. Sidenote: Although the PropertyStream-format is somewhat verbose it is well suited for on-disk compression.

ArmDB / Client using PRich is more sensitive to RAM but you have a great flexibility in how much data they actually have to subscribe to.

This is because the default implementations of IP in ARCCore- are chosen dynamically according to need.
See for instance use of the PValue<T> class, which will be dynamically replaced with a PRich instance if a need for storing meta-data like Cid, Created or similar arises.

Therefore, if a Subscription does include any of this meta-data, then only a PValue<T> instance will be created at the subscriber side, meaning single nodes in the system can have reduced memory consumption just by judiciously chosing what data is needed.

Use the PExact<EnumType> class as basis for your 'entity' classes when you know exact what you want to store in them and when you do not need to store any meta-data like Cid and Created.

See also BoilerplateCodePropertiesAndStorage which offers automatically generated boilerplate code for turning your class into a memory-efficient traditional C# class. This can be done independently by different nodes in the system, that is, you only have to implement properties that you actually need in the given context (remember that even null values for a property still occupies 8 byte of memory, so it is best to leave it out completely).
Note that by default the property storage mechanism normally used in AgoRapide (like in PRich) will not waste memory on non-existing properties at all because of the dictionary mechanism used (albeit with a significant overhead).

Description, EnumMember, EnumType
NoRealDeletionAgoRapide has no real concept for deletion of data (apart from DataRetention, which is mostly relevant for 'old' data).
The closest concept is setting Invalid for a property.

There might also be regulatory concerns demanding that you actually delete data as requested in your application.
(for instance deleting data for a specific customer. This will be more difficult though since AgoRapide does not have any concept of WHERE in the property stream a given datapoint resides).
TODO: Implement 'Delete' as a command verb on the PropertyStream.


Description, EnumMember, EnumType
PropertyAccessThe general mechanism for accessing properties of objects in AgoRapide.

Implemented through the IP (IProperty) interface mechanism.

In applications with lot of different data fields it might be difficult to 1) Specify from the beginning exactly which fields you need, 2) To decide if they are actually available at the stage of processing, 3) To explain them in logs and debug-messages and 4) To implement storage for them.

This can lead to a messy bug-prone implementation because you have to make assumptions about the data available, or you just leave out desired functionality because of a constant need for generating boilerplate code just to accomplish what is really a trivial task that should be inbuilt / automated somehow from the beginning.TODO: CLARIFY SENTENCE ABOVE.

AgoRapide uses a standardized generic mechanism for accessing properties of objects. It is implemented through the IP (IProperty) interface mechanism

This means that for every field / property you have concepts like the following ready for use:

1) Both Get and TryGet are always available. Get will throw a detailed exception if not successful (see default interface methods in IP like TryGetV)

2) Get has the choice of a default value to return if not successful (instead of throwing an exception) (see default interface methods in IP like -GetV-).

3) Meta-information for a property, like who created it or how old it is (see PP like Cid and Created).

4) Defining cardinality like single, multiple and so on (with corresponding validation and parsing) (see Cardinality).

5) Whether the field is obligatory or not (see IsObligatory).

6) Default value (see DefaultValue).

7) Guard against multiple setting of same property (see -SetP- versus AddP, the latter throws a -KeyAlreadyExistsException- for multiple attempts to set a property)
TODO: Regarding 7), introduce in PKTypeAttribute a setting for this (SetOnlyOnceAllowed or similar)
TODO: but remember that must then be honoured by all implementations of AddP and
TODO: you must also think through implications when updating object from the property stream

At the entity level (IP-level), you get the following:
1) Automatic assertion of integrity (assertion that IsObligatory values are set for instance, see AssertIntegrity).

2) An automatic ToString() method for your objects (not even with boilerplate auto-generated code but all automatically from within the framework itself).
TODO: Actually not implemented as of May 2020, but 'easily done'.

3) A truly 'deep' copy is always possible (see DeepCopy).

4) Changes are automatically logged (see log and ExposingApplicationState).

See also ITypeDescriber which extends the idea of a standardized parsing and validation mechanism to single property-values also

Description, EnumMember, EnumType, LongDescription
PropertyStreamAgoRapide, the 'streams-of-water' database".

Property stream in AgoRapide is the concept of how all data is broken down into single 'key and value' pairs (single PropertyStreamLines) which are stored sequentially as plain text format lines and then never changed.

See PropertyStreamLine for the actual syntax used.

The resulting 'property stream' is, by its own nature, easy to distribute.

It is also easy to convert into an object oriented format, lessening the 'impedance mismatch' issue between databases and object oriented languages (see TryParse and TryStore.
Note that conversion back again is also possible, see ToPropertyStream.

Some examples of what the property stream concept makes easier are:

1) Implementing the actual storage.
AgoRapide offers its own storage mechanism (see StreamProcessor).
(Note that this is not obligatory, see ARCSync for how to synchronize AgoRapide from other databases.)

2) Preservation of history.
Storing data in traditional 'database tables' is actually only preserving the current status, with special provisions having to be taken in order to also preserve history. With the property stream concept on the other hand, history is automatically (intrinsically) preserved. (and the traditional 'table' can always be created from the property stream, but not vice versa).

3) Distribution of data.
Thanks to your data flowing like 'streams-of-water', it can be piped wherever convenient (by a publish / subscribe mechanism), to caches, to sub-systems and so on (see StreamProcessor, Subscription and ClientUpdatePosition).

4) Security.
Instead of a traditional API connecting to a 'complete' database backend (with the corresponding security implications), you can have non-sensitive data streamed to dedicated API nodes. Because these nodes can only serve non-sensitive data, they are easier to implement in a secure manner.

5) Coherent representation throughout your application.
The same format is used 'everywhere' like:
a) In the storage file: 'Customer/42/FirstName = John'
b) As an HTTP API call: 'yourapi.com/Customer/42/FirstName = John'
c) As a query (through API or otherwise): 'yourapi.com/Customer/42'

6) Load-balancing.
(see Sharding).

7) Fault-tolerance.
(see MultipleConnectionUsage).

8) Always up-to-date incremental backup.
A backup node can simply subscribe to -IsAll-, '+*', and thereby keep an always current backup).

Note especially how distributed systems are easy to implement with AgoRapide because synchronizing data across different ARNodeType is very easy when properties 'flow like water'.

For serialization of objects see ToPropertyStream and
for deserialization see -ParseAndStore-.


Description, EnumMember, EnumType, LongDescription
SingleThreadedCodeSome practical choices have been made in AgoRapide which requires object access to be done in a single-threaded manner, or within a locking context (using for instance -ReaderWriterLockSlim-).

Examples are like
1) In objects like PRich, using System.Collections.Dictionary instead of System.Collections.Concurrent.ConcurrentDictionary due to memory concerns and (when building a hierchical object model) due to the inherent dangers for bugs that a multi-threaded model would bring).

Note hints in the documentation for how to write thread safe applications, for instance documentation for OutsideLocalReceiver. Also note objects like PConcurrent which may be used when you definitely need multi-threaded access.

The inbuilt distributive possibilities in AgoRapide is supposed to be a good fit with this restriction. If you need more processing power than what a single main-thread can give you, then it is very easy to distribute load over multiple ARNodeType nodes. Each of these nodes should anyway only have to do a simple easy to understand task, and then a single main thread should be no real restriction.

Note that where relevant AgoRapide does of course make extensive use of multithreaded code, ascynchronous code (async / await) and so on.


Description, EnumMember, EnumType
StandardAgoRapideCodeCode originating from the main official AgoRapide distribution (which therefore does not include any end-application specific code)

TODO: Consider creating new enum CodeLocation or similar,
TOOD: comprising StandardAgoRapideCode and ApplicationSpecificCode.

Although AgoRapide is open-source with an extremely flexible license (and you may therefore mix its code with your own), it is anyway recommended to keep core parts of the system, like all CoreDB and as many of ArmDB as possible, based on only the official AgoRapide distribution, that is, without any ApplicationSpecificCode. Following this recommendation will ensure greater stability for the critical core parts of your system.

A node with only StandardAgoRapideCode therefore most probably knows very little about end-application specific types. Although by compiling it with only the standard AgoRapide code it will be able to receive some PK information (through the PropertyStream), it will not be able to do any type-specific operations.
For example: With something like 'Customer/42/PhoneNumber = +4790534333' it will understand that 'Customer' is a IKType, '42' is a IKString, and 'PhoneNumber' is a ITypeDescriber, but it will not be able to actually create a Customer-object nor a PhoneNumber because the definition for those types are unknown (the types are not present in the assemblies constituting the application).

Description, EnumMember, EnumType
TaggingOfPropertyKeysThe concept of specifying in a single place all relevant information about a given property (data field).

The purpose is to give 'at-a-glance' information about all relevant aspects of a given property, without having to navigate through a complex code database. And also with the goal of reducing the amount of ApplicationSpecificCode.

Note: You can start using AgoRapide without this concept.
AgoRapide as a storage system is usable without define ANY schema / tagging at all. Just create PropertyStreamLines and see how they immediately gets understood by a standard ARAAPI application.

See PK, / BasePKAttribute where the tagged attributes are stored.

This central concept in AgoRapide (in addition to PropertyStream) ensures that once you have decided that you need a field like for instance 'Customer.FirstName' then all of the functionality (or as much as possible of it) for that field can reside in the C# code where it was originally defined / declared.

TODO: Give som practical examples of what is meant by this.

In the rest of your application logic there should be less need for referring to 'FirstName'. Like implementing setters and getters, reading from and storing to database, logging access, storing historical data, UI-presentation (including transformations and joins), input-validation and so on.

In other words, all application logic related to 'FirstName' should reside where 'FirstName' was originally defined, enabling you to at-a-glance ascertain how FirstName is used throughout the application.

If all this can be sewn together in a coherent manner then a huge amount of boilerplate code disappears. This again will help with keeping the complexity of your application down as it matures.
In practise, all this is accomplished by you (the user of AgoRapide) by defining enums tagged as PropertyKeyEnum. (Example: See how StreamProcessorP is tagged as '[Enum(AREnumType = AREnumType.PropertyKey)]'.)

The values of these enum definitions again are tagged through the BasePKAttribute mechanism.
(Example: See how LocalStorageFolder is tagged with PKTypeAttribute's 'Description' and 'IsObligatory'.)

The end-result of all this tagging ends up in a PK instance (which may contain multiple BasePKAttribute instances).
(Example: CountSendMessage is tagged by both a PKTypeAttribute and a PKLogAttribute.)

ARCCore contains some implementations of BasePKAttribute like PKTypeAttribute (which will always be available for a given property) and PKLogAttribute.
The other ARComponents introduce more implementations of BasePKAttribute in order to implement their functionality.
TODO: Give examples here.
You are also strongly encouraged to write your own classes inheriting BasePKAttribute whenever you have code implementing some specific aspects about a property key.
TODO: INSERT EXAMPLE HERE OF CUSTOM-BUILT BasePKAttribute.

For some easy-to-follow examples of this, see ARCDoc.

Description, EnumMember, EnumType, LongDescription
TryPatternAndNullAgoRapide uses non-nullable reference types as default throughout the system

(through the setting <PropertyGroup><Nullable>enable</Nullable></PropertyGroup> in the .csproj-files).

However, the TryGet- / TryParse-pattern does not work well with non-nullable reference types. A compromise is being used in AgoRapide where actually null! is set for the out-value when return value is FALSE. Assuming correct client-usage, this use of null! is considered to be an acceptable compromise. For more details, see https://softwareengineering.stackexchange.com/questions/387674/c-8-non-nullable-references-and-the-try-pattern

Description, EnumMember, EnumType

21 items


Generated 2020-10-13 11:11:01.220 UTC