2012-09-12 32 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; 
     } 
    } 
}