2

Let's assume that I have this scenario: I have got 2 repositories of information, and I want to access both, but it would be nice to leave the task of deciding which repo to use to common class.

The goal is to accomplish this with something similar to the code I've wrote below, but this sounds pretty bad:

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

Sure I can ommit that, but bassically what I'm asking is what to do in order to stop using reflection and go typed. Maybe any design-pattern recomendation?

Code (if you copy/paste this on a console app replacing the Program class you should be able to run the example)

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

Thanks in advance!

4

2 回答 2

0

如果你们中的任何人感兴趣,我不得不改变我这样做的方式,因为它正在检查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;
        }
    }
}
于 2012-09-14T21:49:29.060 回答
0

您可以添加 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;
    }
}
于 2012-09-12T20:37:43.817 回答