using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Runtime.Remoting.Activation; using System.Runtime.Remoting.Contexts; using System.Runtime.Remoting.Messaging; using System.Threading; namespace ContextMatters { [DatabaseObject] class Division : ContextBoundObject { string name; int headCount; public string Name { get { return name; } set { name = value; } } public int HeadCount { get { return headCount; } set { headCount = value; } } } class DivisionSameContext { string name; int headCount; public string Name { get { return name; } set { name = value; } } public int HeadCount { get { return headCount; } set { headCount = value; } } } class DatabaseObjectAttribute : ContextAttribute { public DatabaseObjectAttribute() : base("DatabaseObject") { } public override bool IsContextOK(Context ctx, IConstructionCallMessage ctorMsg) { // pokud kontext obsahuje nasi property, tak ho klidne muzeme pouzit i na tenhle objekt return ctx.GetProperty(DatabaseObjectContextProperty.PropertyName) != null; } public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg) { // vlastnost kontextu vytvori sink ctorMsg.ContextProperties.Add(DatabaseObjectContextProperty.Instance); } } class DatabaseObjectContextProperty : IContextProperty, IContributeObjectSink { public const string PropertyName = "DatabaseObject"; public static readonly DatabaseObjectContextProperty Instance = new DatabaseObjectContextProperty(); DatabaseObjectContextProperty() { } void IContextProperty.Freeze(Context newContext) { } bool IContextProperty.IsNewContextOK(Context newCtx) { // jakejkoliv kontext se nam libi return true; } public string Name { get { return PropertyName; } } IMessageSink IContributeObjectSink.GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink) { // IContributeObjectSink zachytava volani na strane volaneho objektu (serveru) return new DatabaseObjectSink(nextSink); } } /// /// Toto je sink, ktery zachytava zpravy /// class DatabaseObjectSink : IMessageSink { readonly IMessageSink next; public DatabaseObjectSink(IMessageSink nextSink) { this.next = nextSink; } public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) { ProcessMessage(msg); return next.AsyncProcessMessage(msg, replySink); } public IMessage SyncProcessMessage(IMessage msg) { ProcessMessage(msg); return next.SyncProcessMessage(msg); } public IMessageSink NextSink { get { return next; } } void ProcessMessage(IMessage msg) { IMethodMessage methodMsg = msg as IMethodMessage; if (methodMsg != null) { //Console.Write("Calling {0}(", methodMsg.MethodName); //for (int i = 0; i < methodMsg.ArgCount; i++) //{ // Console.Write(methodMsg.GetArg(i)); // if (i < methodMsg.ArgCount - 1) Console.Write(", "); //} //Console.WriteLine(")"); } } } class Program { const int Iterations = 1024;// * 1024; static void Main(string[] args) { HiPerfTimer timer = new HiPerfTimer(); timer.Start(); for (int i = 0; i < Iterations; i++) { Division division = new Division(); division.Name = "Services"; division.HeadCount = 42; } timer.Stop(); double bound = timer.Duration; Console.WriteLine("Context-bound object created and called {0} times. Duration = {1} s", Iterations, bound); timer.Start(); for (int i = 0; i < Iterations; i++) { DivisionSameContext division = new DivisionSameContext(); division.Name = "Services"; division.HeadCount = 42; } timer.Stop(); double agnostic = timer.Duration; Console.WriteLine("Context-agnostic object created and called {0} times. Duration = {1} s", Iterations, agnostic); Console.WriteLine("Context-bound was {0} times slower.", (bound / agnostic)); Console.ReadKey(); } } public class HiPerfTimer { [DllImport("Kernel32.dll")] private static extern bool QueryPerformanceCounter(out long lpPerformanceCount); [DllImport("Kernel32.dll")] private static extern bool QueryPerformanceFrequency(out long lpFrequency); private long startTime, stopTime; private long freq; // Constructor public HiPerfTimer() { startTime = 0; stopTime = 0; if (QueryPerformanceFrequency(out freq) == false) { // high-performance counter not supported throw new Win32Exception(); } } // Start the timer public void Start() { // lets do the waiting threads there work Thread.Sleep(0); QueryPerformanceCounter(out startTime); } // Stop the timer public void Stop() { QueryPerformanceCounter(out stopTime); } // Returns the duration of the timer (in seconds) public double Duration { get { return (double)(stopTime - startTime) / (double)freq; } } } }