www.espertech.comDocumentation
This section provides information for NEsper .NET users.
System.Collections.IEnumerable
and System.Collections.Generic.IEnumerable<T>
are honored in most places where a collection would be taken.
In respect to DateTime
differences, the baseline for CLR datetimes is 1/1/0001 12:00:00AM
. DateTimes are converted to ticks and then to milliseconds.
Annotations are implemented using .NET attributes. Annotations must derive from System.Attribute
and must use .NET attribute naming conventions e.g. @Hint
is implemented as HintAttribute
.
NEsper provides a lock manager that is configurable once per AppDomain: com.espertech.esper.compat.threading.LockManager
is used for lock provision.
Standard system locks are the default.
Spinlocks & Slimlocks may be used.
Custom lock implementations can be leveraged.
Out of the box the following are the lock implementations:
MonitorLock - uses the CLR provided object locking mechanism, equivalent to java's wait() and notify()
MonitorSpinLock - uses the CLR provided System.Threading.SpinLock
MonitorSlimLock - early model of spin lock that I built for NEsper
com.espertech.esper.compat.threading.ReaderWriterLockManager
is used for RW lock management.
Standard reader writer locks are the default.
SlimReaderWriter locks are provided.
Fair & FIFO ReaderWriter lock implementations are provided but not officially supported.
ReaderWriterLocks are a separate construct and out of the box implementations include:
StandardReaderWriterLock - uses the CLR provided System.Threading.ReaderWriterLock()
SlimReaderWriterLock - uses the CLR provided System.Threading.ReaderWriterLockSlim()
FifoReaderWriterLock - built to mirror some of the Java reader writer semantics - generally not recommended and not officially supported by NEsper
FairReaderWriterLock - built to mirror some of the Java reader writer semantics - generally not recommended and not officially supported by NEsper
In NEsper there is a container that is provided or created during initialization.
DefaultReaderWriterLockManager rwLockManager = (DefaultReaderWriterLockManager) container.RWLockManager();
Once the application has the lock manager, it can set the DefaultLockTimeout property on it.
rwLockManager.DefaultLockTimeout = 1000000L;
The lock manager relies on a factory. The default factory can be overridden by setting the DefaultLockFactory property.
rwLockManager.DefaultLockFactory = (lockTImeout) => ...();
If the application would like to control this by type, it can register a specific lock factory for a given type.
rwLockManager.RegisterLockFactory(typeof(foo), (lockTimeout) => myCustomerLock());
There are no per-type lock timeouts.
com.espertech.esper.compat.threading.ThreadLocalManager
is used for thread local management.
Fast thread local implementation is the default - not .NET standard.
Standard implementation is available - however, it is found significantly slower.
This section only applies to internal system-time timer and does not apply to external timer (when your application provides time).
Since often running on windows, NEsper by default relies on the high performance multimedia timer. This timer is designed to allow for synchronization to the display rate and so it can run at 1ms or better. High resolution timers are cleaned up when the AppDomain is disposed.
However, if the application is netcoreapp and since netcoreapp is designed to run in a cross platform way, one would want to rely on the standard timers provided by .NET.
In order to use an alternative timer one must configure the container (as follows). This will tell the container to create a SimpleTimerFactory
. The default behavior is preserved but you can now change the behavior to use a less CPU consuming timer.
var container = ContainerExtensions.CreateDefaultContainer(false); container.Register<ITimerFactory>( ic => new SimpleTimerFactory(), Lifespan.Singleton); container .InitializeDefaultServices() .InitializeDatabaseDrivers(); var config = new Configuration(container); var esperRuntime = EPRuntimeProvider.GetRuntime("URI Here", config);
The above code creates a container, registers the service(s) that an application may want, and then initializes defaults for any remaining services and database drivers.
InitializeDefaultServices()
initializes the container with default services if none have been provided. So if a service of any kind is to be provided, it must be added to the container prior to calling InitializeDefaultServices()
.
Otherwise, the default services will be installed and will actively throw an exception if there is an attempt to replace the registered service. CreateDefaultContainer(false)
does nothing more than instantiate a new Container object.
com.espertech.esper.util.EsperSectionHandler
is provided to read Esper configuration from standard .NET configuration. It must be added as a configSection
in order to be used.
For items not handled under the Esper configuration use com.espertech.esper.compat.CompatSettings
.
These are often applied for the entire AppDomain meaning they are effectively static for the container.
These cover the following items:
DefaultLockType
.
DefaultReaderWriterLockType
.
MonitorLockTimeout
.
ReaderLockTimeout
.
WriterLockTimeout
.
DefaultThreadLocalType
.
Table J.1. Event Underlying .NET Objects
Java Class | Description |
---|---|
System.Object | Any .NET object with properties. |
System.Collections.Generic.IDictionary | Map events are implementations of the IDictionary interface where each map entry is a propery value. |
System.Array, System.Object[] (array of object) | Object-array events are arrays of objects (type Object[] ) where each array element is a property value. |
System.Xml.XmlNode and System.Xml.Linq.XNode | XML document object model (DOM). |
Application classes | Plug-in event representation via the extension API. |
Event classes provide accessors (getter methods) and mutators (setter methods) by means of auto-implemented properties or read write properties.
Below an example using auto-implemented properties:
class NewEmployeeEvent { public string FirstName { get; set; } public Address Address { get; set; } }
Below an example using read write properties:
class NewEmployeeEvent { private string firstName = "N/A"; private Address address = 0; public string FirstName { get { return firstName; } set { firstName = value; } } public Address Address { get { return address; } set { address = value; } } }
The case conversion is uppercase as dictated by .NET property conventions.
Mapped indexes are handled through the indexing operator.
For .NET the events can be represented by objects that implement the IDictionary
interface.
Objects need to follow the .NET property conventions. Objects can follow modified conventions for Java-style accessors and mutators using Get and Set respectively.
There are no differences between Esper and NEsper in respect to basic concepts.
The data types are sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, float
, double
, decimal
.
.NET uses ADO-based drivers to accomplish the same work.
NEsper exposes the Events events
on EPStatement
objects.
UpdateListener
is replaced by UpdateEventHandler
in .NET. Subscriber objects must implement the Update
method
or subscriber objects must be a delegate with an appropriate number of arguments.
The setSubscriber
method is replaced with the Subscriber
property. This property can take an object or a delegate.
Iterator
is replaced with GetEnumerator
. SafeIterator
is replaced with GetSafeEnumerator
.
In NEsper you can assign a delegate to a subscriber using lamba this way:
statement.Subscriber = new Action<TradeReportEvent, NesperTest>((a, b) => { Debug.Print("got here"); });
Listeners are replaced with UpdateEventHandlers
, for example countStatement.Events += (sender, args) => { DoWork(); }
.
Connections are obtained by selecting a DbDriver
, which are a NEsper-construct.
DbDriverGeneric
: Positional or name based driver that must be completely configured prior to use.
DbDriverMySQL
: Positional based driver that uses '?' prefix.
DbDriverODBC
: Positional based driver that uses '?' prefix.
DbDriverSqlServer
: Translates positional into named-based SqlParameters with '@' prefix.