Note that there are some explanatory texts on larger screens.

plurals
  1. POOnline-Offline Class Manager
    primarykey
    data
    text
    <p>Ok, first I'll describe my <strong>goal</strong>, then what I've <strong>coded</strong>, finally <strong>questions</strong>.</p> <h2>Goal</h2> <p>To have a <strong>generic class</strong> that manage multiple <em>contracts</em> that , and is able to find out wheter it's an online or offline situation, on the very moment when an operation is being made. There's a really easy way of doing it: a class for each Online-Offline pair that implement the contract and check on every each method wheter if it's online or not, and makes the right call. And that's exactly what I want to avoid.</p> <p>Just FYI, behind the scenes it would be an <em>Online scenario</em> connected to <strong>WCF services</strong> and an <em>Offline scenario</em> connected to a <strong>client local database</strong>.</p> <p>FYI 2: I've tried to accomplish this avoiding Interception and AOP stuff, but I found a dead end. You can see <a href="https://stackoverflow.com/questions/12395778/how-to-code-a-good-offline-online-dispatcher"><strong>this post</strong></a> where I implement what seems to be a good solution, but stablishes if it's connected or not on the <em>contructor</em>, but real-world scenario needs this check at <em>Operation level</em>, not <em>constructor level</em>.</p> <h2>Code</h2> <p>It's ready to run &amp; test: just copy/paste on a new console application.</p> <pre><code>using System; using System.Reflection; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.InterceptionExtension; namespace ConsoleApplication1 { public class Unity { public static IUnityContainer Container; public static void Initialize() { Container = new UnityContainer(); Container.AddNewExtension&lt;Interception&gt;(); Container.RegisterType&lt;ILogger, OnlineLogger&gt;(); Container.Configure&lt;Interception&gt;().SetInterceptorFor&lt;ILogger&gt;(new InterfaceInterceptor()); } } class Program { static void Main(string[] args) { Unity.Initialize(); var r = new Router&lt;ILogger, OnlineLogger, OfflineLogger&gt;(); try { r.Logger.Write("Method executed."); } catch (CantLogException ex) { r.ManageCantLogException(ex); } Console.ReadKey(); } } public class Router&lt;TContract, TOnline, TOffline&gt; where TOnline : TContract, new() where TOffline : TContract, new() { public TContract Logger; public Router() { Logger = Unity.Container.Resolve&lt;TContract&gt;(); } public void ManageCantLogException(CantLogException ex) { // Is this an ugly trick? I mean, the type was already registered with online. Unity.Container.RegisterType&lt;TContract, TOffline&gt;(); Logger = Unity.Container.Resolve&lt;TContract&gt;(); var method = ((MethodBase)ex.MethodBase); method.Invoke(Logger, ex.ParameterCollection); } } public interface ILogger { [Test] void Write(string message); } public class OnlineLogger : ILogger { public static bool IsOnline() { // A routine that check connectivity return false; // Should I perform a "lock" here to make this tread safe? } public void Write(string message) { Console.WriteLine("Logger: " + message); } } public class OfflineLogger : ILogger { public void Write(string message) { Console.WriteLine("Logger: " + message); } } [System.Diagnostics.DebuggerStepThroughAttribute()] public class TestAttribute : HandlerAttribute { public override ICallHandler CreateHandler(IUnityContainer container) { return new TestHandler(); } } public class TestHandler : ICallHandler { public int Order { get; set; } public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { Console.WriteLine("It's been intercepted."); if (!OnlineLogger.IsOnline() &amp;&amp; input.Target is OnlineLogger) { Console.WriteLine("It's been canceled."); throw new CantLogException(input.MethodBase, input.Inputs); } return getNext()(input, getNext); } } public class CantLogException : Exception { public MethodBase MethodBase { get; set; } public object[] ParameterCollection { get; set; } public CantLogException(string message) : base(message) { } public CantLogException(MethodBase methodBase, IParameterCollection parameterCollection) { this.MethodBase = methodBase; var parameters = new object[parameterCollection.Count]; int i = 0; foreach (var parameter in parameterCollection) { parameters[i] = parameter; i++; } this.ParameterCollection = parameters; } } } </code></pre> <h2>Questions</h2> <ol> <li><p>Is this design that I present thread-safe?</p></li> <li><p>Is it a performance disgrace? The exception handling the Online-Offline situation and reflection there makes me fell I'm doing all wrong.</p></li> <li><p>I think this is a common requeriment, isn't there any api/fwk/whatever that does this Online-Offline management? Kind of feel like I'm reinventing the weel here.</p></li> <li><p>This is a long shot question: I really don't want client (<strong>Program</strong> class on this example) to know about the exception, isn't there any other way to <strong>cancel</strong> method execution but through an exception on the interceptor? Any other approach is welcomed too.</p></li> </ol> <hr> <p>I'm not interested on paid third-party stuff, so sadly things like <a href="http://www.sharpcrafters.com/" rel="nofollow noreferrer"><strong>PostSharp</strong></a> aren't options for me.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload