www.espertech.comDocumentation

Appendix J. NEsper .NET -Specific Information

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.

Out of the box the following are the lock implementations:

com.espertech.esper.compat.threading.ReaderWriterLockManager is used for RW lock management.

ReaderWriterLocks are a separate construct and out of the box implementations include:

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.

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:


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.

XML events are represented by System.Xml and System.Xml.Linq.

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.

Log4j is replaced by .NET Commons Logging.