【问题标题】:How to code a good Offline-Online Dispatcher如何编写一个好的离线在线调度程序
【发布时间】:2012-09-12 20:31:03
【问题描述】:

假设我有这种情况:我有 2 个信息存储库,我想访问这两个存储库,但最好将决定使用哪个存储库的任务留给 通用类

我们的目标是使用与我在下面编写的代码相似的东西来完成此任务,但这听起来很糟糕:

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

当然我可以省略这一点,但基本上我要问的是如何才能停止使用反射并键入。也许有任何设计模式推荐?

代码(如果您将其复制/粘贴到替换 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();
    }
}

提前致谢!

【问题讨论】:

标签: c# design-patterns generics


【解决方案1】:

你可以添加 new() 约束:

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;
    }
}

【讨论】:

  • 无法将类型“TOffline”隐式转换为“TContract”。您可以根据需要运行示例,代码已准备好用于控制台应用程序。
  • 对,对不起,我更新了我的答案。您还可以将 TContract 约束添加到 TOnline 和 TOffline。
  • 太棒了!这正是我想要的!谢谢!
  • 顺便说一句,你认为这是一个好方法吗?
【解决方案2】:

如果你们有兴趣,我不得不改变我这样做的方式,因为它在 Constructor Level 检查连接,而我需要在 Operation Level 进行检查>.

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;
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    • 1970-01-01
    相关资源
    最近更新 更多