在仍使用依赖注入的同时创建新实例

Oni*_*mus 6 c# dependency-injection ioc-container unity-container

快速描述环境:

我有一个代表聊天室的类,并且依赖于记录器.它与具有横切关注点的系统级记录器不同,而是与特定聊天室相关联的记录器.它将该聊天室中的所有活动记录到其唯一的日志文件中.创建聊天室时,我想打开日志文件,当它被销毁时,我想关闭日志文件.

问题

这是我正在使用的相关代码.

public interface IChatroomLogger
{
    void Log(ServerPacket packet);
    void Open();
    void Close();
}

public class ChatroomLogger : IChatroomLogger
{
    // chatroom name will be used as a file name
    public ChatroomLogger(string chatroomName) { ... }
    public void Log(ServerPacket packet) { ... }
}

public class Chatroom
{
    public Chatroom(string name, IChatroomLogger logger)
    {
        this.name = name;
        this.logger = logger;
        this.logger.Open();
    }

    public IChatromLogger Logger { get { return this.logger; } }
}

public interface IChatManager
{
    Chatroom Get(chatroomName);
}
Run Code Online (Sandbox Code Playgroud)

它在这样的应用程序中使用:

var room = ChatManager.Get(chatroomName);
romm.DoStuff();
room.Logger.LogPacket(receivedPacket);
Run Code Online (Sandbox Code Playgroud)

ChatManager是一个包含所有聊天室引用的类,负责创建和删除它们.我还没有写它,但这是我编写的接口.

问题

我如何ChatManager创建新的实例Chatroom并仍然使用依赖注入?

我正在使用Unity来完成我所有其他的DI工作.到目前为止它的效果很好.但我不知道如何解决这个难题.

当我的具体实现ChatManager创建新的聊天室时,它必须通过一个IChatroomLogger.它不知道如何构建......但Unity确实如此.但后来我必须IUnityContainer进入ChatManager.

public class ChatManager : IChatManager
{
    public ChatManager(IUnityContainer container)
    {
        this.container = container;
    }

    public Chat Get(string chatroomName)
    {
        // get logger from Unity somehow. Not sure how I'd 
        // pass chatroomName to the concrete instance
        var logger = ...
        return new Chatroom(chatroomName, logger);
    }
}
Run Code Online (Sandbox Code Playgroud)

出于某种原因,这似乎是错误的.如果没有域名知道我正在使用什么DI容器,这似乎更清晰.

如果Chatroom我的应用程序在运行过程中没有求助于某种服务定位器设计,我怎么能得到新的类实例?我是否在思考它?绕过Unity是不是一件大事?欢迎任何想法!

Str*_*ior 4

你说得对。像这样使用IUnityContainer就不再使用依赖注入了。相反,它使用“服务定位器”模式。在这种情况下,我通常会创建一个IFactory<T>接口,如下所示:

public IFactory<T>
{
    T Get();
}
Run Code Online (Sandbox Code Playgroud)

然后使用一个了解使用IUnityContainer. 设置您的绑定,以便IFactory<>请求将创建此工厂类的实例。这样,您可以将IFactory<Logger>接口注入到您的 中ChatManager,并.Get()在需要记录器实例时随时调用。