共享依赖引用

时间:2015-03-25 03:39:48

标签: c# interface dependency-injection abstraction

我的域层中有一个IClientConnection接口,负责连接到IRC服务器。我想隐藏与服务层后面的服务器的通信。

服务接口

我创建了几个服务接口。 IIrcConnectionService提供了两种方法,ConnectToServerDisconnect。它处理与IClientConnection实现的对话。第二个服务接口是IChannelService,提供了两种方法,JoinChannelPartChannel

public class IrcConnectionService : IIrcConnectionService
{
    /// <summary>
    /// The client connection
    /// </summary>
    private IClientConnection clientConnection;

    /// <summary>
    /// The connected completed callback
    /// </summary>
    private Action connectedCompletedCallback;

    /// <summary>
    /// Initializes a new instance of the <see cref="IrcConnectionService"/> class.
    /// </summary>
    /// <param name="clientConnection">The client connection.</param>
    public IrcConnectionService(IClientConnection clientConnection)
    {
        this.clientConnection = clientConnection;
    }

    /// <summary>
    /// Connects to server.
    /// </summary>
    /// <param name="serverInfo">The server information.</param>
    /// <param name="userInfo">The user information.</param>
    /// <returns>Returns an awaitable Task</returns>
    public Task ConnectToServer(ServerConnectionInfo serverInfo, UserInformation userInfo, Action connectedCompletedCallback = null)
    {
        if (connectedCompletedCallback != null)
        {
            this.connectedCompletedCallback = connectedCompletedCallback;
            this.clientConnection.Connected += this.OnClientConnected;
        }

        IrcConnectionService.CacheConnection(this.clientConnection);
        return this.clientConnection.Connect(serverInfo, userInfo);
    }

    private void OnClientConnected(object sender, EventArgs e)
    {
        this.connectedCompletedCallback();
    }


    /// <summary>
    /// Disconnects from server.
    /// </summary>
    /// <param name="serverInfo">The server information.</param>
    public void DisconnectFromServer(ServerConnectionInfo serverInfo)
    {
        this.clientConnection.Connected -= this.OnClientConnected;
        this.clientConnection.Disconnect();
    }
}

public class ChannelService : IChannelService
{
    private IIrcConnectionService connectionService;

    private IClientConnection connection;

    public ChannelService(IIrcConnectionService connectionService)
    {
        this.connectionService = connectionService;
    }

    public Task JoinChannel(string server, string channelName, string password = "")
    {
        if (!this.connectionService.IsConnected)
        {
            throw new InvalidOperationException("You must connect to a server prior to joining a channel.");
        }

        if (!channelName.StartsWith("#"))
        {
            channelName = channelName.Insert(0, "#");
        }

        return this.connectionService.SendMessage($"JOIN {channelName}");
    }

    public Task PartChannel(string serverNaemstring channelName)
    {
        throw new NotImplementedException();
    }
}

应用程序可以连接到多个服务器。因此依赖注入容器(Unity)不会将它们注册为单例。相反,它会在每次需要时创建一个新实例。

此处的麻烦现在变为在同一服务的多个实例中共享IClientConnection实例,或根据需要分享不同的服务。例如,我的视图模型使用IIrcConnectionService的实例连接到服务器,然后使用IChannelService加入频道。当对JoinChannel的调用发生时,该服务的空IClientConnection因为我不知道应该采取什么路由以便为它提供由拥有的IIrcConnectionService共享的相同引用连接。

public class ShellViewModel
{
    /// <summary>
    /// The irc connection service
    /// </summary>
    private IIrcConnectionService ircConnectionService;

    /// <summary>
    /// The channel service
    /// </summary>
    private IChannelService channelService;

    /// <summary>
    /// Initializes a new instance of the <see cref="ShellViewModel"/> class.
    /// </summary>
    /// <param name="connectionService">The connection service.</param>
    public ShellViewModel(IIrcConnectionService connectionService, IChannelService channelService)
    {
        this.ircConnectionService = connectionService;
        this.channelService = channelService;

        this.InitializeCommand = DelegateCommand.FromAsyncHandler(this.Initialize);
    }

    /// <summary>
    /// Gets the initialize command.
    /// </summary>
    public DelegateCommand InitializeCommand { get; private set; }

    /// <summary>
    /// Initializes this instance.
    /// </summary>
    /// <returns>Returns an awaitable Task</returns>
    private async Task Initialize()
    {
        var serverInfo = new ServerConnectionInfo { Url = "chat.freenode.net" };
        var userInfo = new UserInformation { PrimaryNickname = "DevTestUser" };

        // Connect to the server
        await this.ircConnectionService.ConnectToServer(
            serverInfo,
            userInfo,
            async () => await this.channelService.JoinChannel("#ModernIrc"));
    }
}

我正在考虑的一件事是构建一个内部ConnectionCache对象。 IIrcConnectionService实现将按服务器名称将其IClientConnection引用推送到它。 IChannelService将从IClientConnection对象通过服务器名称请求ConnectionCache

这听起来像是有效路径吗?有没有我可以看到的模式来解决这个问题?对此有任何指导意见。

0 个答案:

没有答案