2012-09-12 31 views
2

我們假設我有這種情況:我有兩個信息庫,並且我想要訪問這兩個信息庫,但是最好離開決定使用哪個回購的任務到普通類如何編寫一個好的離線在線調度程序

目標是與類似到我下面寫的代碼的東西做到這一點,但是這聽起來很糟糕:

where TOnline : class 
where TOffline : class 
where TContract : class 

相信我能ommit這一點,但bassically就是我要問是爲了停止使用反射和去鍵入。也許任何設計模式 recomendation?

代碼(如果你複製/粘貼在一個控制檯應用程序替換Program類,你應該能夠運行示例)

using CustomerDispatcher = DispatcherProxy<CustomerOnline, CustomerOffline, ICustomer>; 

public interface ICustomer 
{ 
    string Get(int id); 
} 

public class CustomerOnline : ICustomer 
{ 
    public string Get(int id) 
    { 
     // Get From intranet DB 
     return "From DB"; 
    } 
} 

public class CustomerOffline : ICustomer 
{ 
    public string Get(int id) 
    { 
     // Get From local storage 
     return "From local storage"; 
    } 
} 

public class DispatcherProxy<TOnline, TOffline, TContract> 
    where TOnline : class 
    where TOffline : class 
    where TContract : class 
{ 
    public TContract Instance { get; set; } 

    public bool IsConnected { get; set; } 

    public DispatcherProxy() 
    { 
     // Asume that I check if it's connected or not 
     if (this.IsConnected) 
      this.Instance = (TContract)Activator.CreateInstance(typeof(TOnline)); 
     else 
      this.Instance = (TContract)Activator.CreateInstance(typeof(TOffline)); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var customerDispatcher = new CustomerDispatcher(); 

     Console.WriteLine("Result: " + customerDispatcher.Instance.Get(1)); 

     Console.Read(); 
    } 
} 

提前感謝!

回答

0

您可以添加新的()約束:

public class DispatcherProxy<TOnline, TOffline, TContract> 
    where TOnline : class, new() 
    where TOffline : class, new() 
    where TContract : class //isn't TContract an interface? 
{ 
    public TContract Instance { get; set; } 

    public bool IsConnected { get; set; } 

    public DispatcherProxy() 
    { 
     // Asume that I check if it's connected or not 
     if (this.IsConnected) 
      this.Instance = new TOnline() as TContract; 
     else 
      this.Instance = new TOffline() as TContract; 
    } 
} 
+0

嗯..不會編譯。 –

+0

什麼是錯誤? –

+0

**不能將類型'TOFFLINE'隱式轉換爲'TContract'**。如果需要,可以運行該示例,代碼已準備好用於控制檯應用程序。 –

0

,以防出現任何你感興趣,我不得不改變我這樣做是因爲它是檢查在構造層次連接的方式,和我需要檢查操作級別

using System; 
using Microsoft.Practices.Unity; 
using Microsoft.Practices.Unity.InterceptionExtension; 

namespace ConsoleApplication1 
{ 
    public enum ConnectionStatus 
    { 
     Online, 
     Offline, 
     System // System checks connectivity 
    } 

    public static class Connectivity 
    { 
     private static ConnectionStatus ConnectionStatus = ConnectionStatus.Offline; 

     public static void ForceConnectionStatus(ConnectionStatus connectionStatus) 
     { 
      ConnectionStatus = connectionStatus; 
     } 

     public static bool IsConnected() 
     { 
      switch (ConnectionStatus) 
      { 
       case ConnectionStatus.Online: 
        return true; 
       case ConnectionStatus.Offline: 
        return false; 
       case ConnectionStatus.System: 
        return CheckConnection(); 
      } 
      return false; 
     } 

     private static bool CheckConnection() 
     { 
      return true; 
     } 
    } 

    public class Unity 
    { 
     public static IUnityContainer Container; 

     public static void Initialize() 
     { 
      Container = new UnityContainer(); 

      Container.AddNewExtension<Interception>(); 
      Container.RegisterType<ILogger, OnlineLogger>(); 
      Container.Configure<Interception>().SetInterceptorFor<ILogger>(new InterfaceInterceptor()); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Unity.Initialize(); 

      var r = new Router<ILogger, OnlineLogger, OnlineLogger>(); 

      Connectivity.ForceConnectionStatus(ConnectionStatus.Offline); 

      Console.WriteLine("Calling Online, will attend offline: "); 

      r.Logger.Write("Used offline."); 

      Connectivity.ForceConnectionStatus(ConnectionStatus.Online); 

      Console.WriteLine("Calling Online, will attend online: "); 

      r.Logger.Write("Used Online. Clap Clap Clap."); 

      Console.ReadKey(); 
     } 
    } 

    public class Router<TContract, TOnline, TOffline> 
     where TOnline : TContract 
     where TOffline : TContract 
    { 
     public TContract Logger; 

     public Router() 
     { 
      Logger = Unity.Container.Resolve<TContract>(); 
     } 
    } 

    public interface IOnline 
    { 
     IOffline Offline { get; set; } 
    } 

    public interface IOffline 
    { 
    } 

    public interface ILogger 
    { 
     [Test()] 
     void Write(string message); 
    } 

    public class OnlineLogger : ILogger, IOnline 
    { 
     public IOffline Offline { get; set; } 

     public OnlineLogger() 
     { 
      this.Offline = new OfflineLogger(); 
     } 

     public void Write(string message) 
     { 
      Console.WriteLine("Online Logger: " + message); 
     } 
    } 

    public class OfflineLogger : ILogger, IOffline 
    { 
     public IOnline Online { get; set; } 

     public void Write(string message) 
     { 
      Console.WriteLine("Offline 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 (!Connectivity.IsConnected() && input.Target is IOnline) 
      { 
       Console.WriteLine("It's been canceled."); 

       var offline = ((input.Target as IOnline).Offline); 

       if (offline == null) 
        throw new Exception("Online class did not initialized Offline Dispatcher."); 

       var offlineResult = input.MethodBase.Invoke(offline, this.GetObjects(input.Inputs)); 

       return input.CreateMethodReturn(offlineResult, this.GetObjects(input.Inputs)); 
      } 

      return getNext()(input, getNext); 
     } 

     private object[] GetObjects(IParameterCollection parameterCollection) 
     { 
      var parameters = new object[parameterCollection.Count]; 

      int i = 0; 
      foreach (var parameter in parameterCollection) 
      { 
       parameters[i] = parameter; 
       i++; 
      } 
      return parameters; 
     } 
    } 
}