Aspects in Bucharest
Aspects in Bucharest.
Tomorrow (today, strictly speaking), Steve and I will be doing the second round of talks on our tour speaking about scalable systems. Microsoft Romania expects 700 (!) people and on Friday we're going to have another 700 in Moscow. Add the 200 people we had on the first event yesterday in Warsaw (which went really well) and we'll have had 1600 people altogether in a single week. Fantastic! Great fun.
On of the things I'll be showing tomorrow (in the context of "programming model extensibility") and which you can build yourself using VS.NET 2003 and my new set of libraries is a little custom "aspect" (or "interceptor" for more old-fashioned thinking people):
using System; using newtelligence.Aspects; using newtelligence.EnterpriseServices; namespace AspectComponentServer { [Serializable] public class MonitorData { private string data; public MonitorData( string data ) { this.data = data; } public string Data { get { return data; } } } public class MonitorAspectAttribute : Attribute, IAspectServerContextLeave, IAspectServerContextEnter { public MonitorAspectAttribute() { } public void OnServerContextEnter(object transparentProxy, System.Runtime.Remoting.Messaging.IMessage message,
System.Reflection.MemberInfo member, System.Reflection.ParameterInfo paramInfo) { Console.WriteLine( "Enter context for method {0}", message.Properties["__MethodName"] ); Console.WriteLine( " -- Setting property into context" ); ContextUtilEx.SetUserProperty( "AspectComponentServer.MonitorAspectAttribute.MonitorData",
new MonitorData("Test information") ); } public void OnServerContextLeave(object transparentProxy, System.Runtime.Remoting.Messaging.IMessage message,
System.Reflection.MemberInfo member, System.Reflection.ParameterInfo paramInfo, bool ReturnValue) { Console.WriteLine( "Leave context for method {0}", message.Properties["__MethodName"] ); MonitorData monitorData =
ContextUtilEx.GetUserProperty( "AspectComponentServer.MonitorAspectAttribute.MonitorData") as MonitorData; Console.WriteLine( " -- Property value found: {0}", monitorData.Data ); } } }
and use it like this
using System; using System.EnterpriseServices; using newtelligence.EnterpriseServices; using newtelligence.Aspects.Constraints; using newtelligence.Aspects; [assembly: ApplicationActivation( ActivationOption.Library)] [assembly: ApplicationAccessControl( false )] namespace AspectComponentServer { [Transaction(TransactionOption.Required)] [EventTrackingEnabled] [MonitorAspect] public class FlightReservation : AspectServicedComponent {
[ContextState]
int jitaSessionState;public string ReserveSeat( [Match("[A-Z]+")] string Airline, [MinLength(1),MaxLength(4),Match("[0-9]+")] string FlightNumber, [Between(1,100)] int Row, [Match("[A-K]")] string Seat, [MinLength(3),MaxLength(3)] string DepartureAirport, [LaterThanToday] DateTime DepartureTime, [MinLength(3),MaxLength(3)] string ArrivalAirport) { ... } public bool ConfirmSeat( [MinLength(1),MaxLength(8),Match("[0-9]+")] string ReservationCode ) { ... } public bool CancelSeat( string ReservationCode ) { .... } } }
Steve said yesterday that the capability to add your own interceptors and my extended "ContextUtilEx" class that allows you to flow arbitrary items in the context is enough to build your own services on top of the Enterprise Services infrastructure much in the same way as COM+ does it internally.
The [ContextState] attribute sits on top the ContextUtilEx and gives you custom "session state" for just-in-time activated components, which means that you can have fields that have context scope and whose values will survive the recycling of the actual object instance across activations. That brings Enterprise Services and ASMX one step closer together in terms of programming models.
If Microsoft wouldn't be grumpy with me if I did it (and they would), I would name my stuff not "newtelligence SDK for Enterprise Services" but rather "COM+ 1.75" ;)