C# 如何将数据传递给注入的服务

C# 如何将数据传递给注入的服务,c#,dependency-injection,inversion-of-control,C#,Dependency Injection,Inversion Of Control,我想编写一个小型WinForms或WPF程序,控制每次只有一个人/计算机通过网络共享使用特定的共享文件。工作时需要在本地复制此文件,工作完成后需要将其复制回网络共享 我想创建一个小的WPF应用程序,只需一个按钮就可以将文件标记为已锁定,在本地复制并打开与该文件扩展名关联的应用程序。关闭此应用程序后,文件将复制回网络共享并释放锁。每台计算机都将使用此应用程序访问该文件,因此不应该是两台计算机同时编辑同一文件 应用程序必须具有某种配置文件,其中包含本地和远程文件夹的路径、文件名以及打开该文件的应用程

我想编写一个小型WinForms或WPF程序,控制每次只有一个人/计算机通过网络共享使用特定的共享文件。工作时需要在本地复制此文件,工作完成后需要将其复制回网络共享

我想创建一个小的WPF应用程序,只需一个按钮就可以将文件标记为已锁定,在本地复制并打开与该文件扩展名关联的应用程序。关闭此应用程序后,文件将复制回网络共享并释放锁。每台计算机都将使用此应用程序访问该文件,因此不应该是两台计算机同时编辑同一文件

应用程序必须具有某种配置文件,其中包含本地和远程文件夹的路径、文件名以及打开该文件的应用程序路径。为了简化应用程序的设置,将通过设置Swindow来完成

我试图用IoC和某种轻量级DI容器(即SimpleInjector)来实现这一点,但我对如何正确实现这一点有一些疑问:

Program.cs

static class Program
{
    [STAThread]
    static void Main()
    {
        var container = Bootstrap();

        // Any additional other configuration, e.g. of your desired MVVM toolkit.

        RunApplication(container);
    }

    private static Container Bootstrap()
    {
        // Create the container as usual.
        var container = new Container();

        // Register your types, for instance:
        container.Register<ILauncher, Launcher>();
        container.Register<IFileSyncService, FileSyncronizer>();
        container.Register<IAppRunnerService, AppRunnerService>();
        container.Register<ILockService, LockService>();

        // Register your windows and view models:
        container.Register<MainWindow>();
        container.Register<ConfigurationWindow>();

        container.Verify();

        return container;
    }

    private static void RunApplication(Container container)
    {
        try
        {
            var app = new App();
            var mainWindow = container.GetInstance<MainWindow>();
            app.Run(mainWindow);
        }
        catch (Exception ex)
        {
            //Log the exception and exit
        }
    }
}
ILauncher接口

public interface ILauncher
{
    void Run();
}
启动器实现

launcher实现将负责协调启动应用程序和编辑文件所需的每个任务。这包括:检查和获取锁、同步文件、执行和监视应用程序是否已关闭。为了遵循单一责任原则(SRP),这是通过注入一些服务来实现的:

public class Launcher : ILauncher
{
    public Launcher(
        ILockService lockService,
        IAppRunnerService appRunnerService,
        IFileSyncService fileSyncService
        )
    {
        LockService = lockService;
        AppRunnerService = appRunnerService;
        FileSyncService = fileSyncService;
    }

    public ILockService LockService { get; }
    public IAppRunnerService AppRunnerService { get; }
    public IFileSyncService FileSyncService { get; }

    public void Run()
    {
        //TODO check lock + adquire lock
        //TODO Sinchronize file
        //TODO Subscribe to the IAppRunnerService.OnStop event 
        //TODO Start app through IAppRunnerService.Run method
    }
}
我的问题是:

  • 使用“new”关键字或手动调用类或窗口中的容器来创建新实例是一种不好的做法,因此桌面应用程序的入口点(通常是某种主窗口)应该(通过构造函数)询问所有内容。当应用程序增长时,这似乎不是一种合适的方式。我说得对吗?解决办法是什么

  • 在我的应用程序中,每个服务都需要某种运行时数据(可执行文件路径、本地或远程目录…)。容器在应用程序执行的早期实例化它们,甚至在知道这些数据之前。服务如何接收这些数据?(请注意,数据可以稍后通过设置Swindow进行修改)

  • 很抱歉延长了这篇文章的篇幅,但我想澄清我的问题和背景

  • 正如您所说,您必须在入口点请求一些服务,但什么是“请求一切”?您的入口点应该只有它直接使用的服务作为参数。如果您的应用程序不断增长,并且突然有十几个服务被您的入口点直接调用,这可能意味着一些服务可以合并成一个更大的数据包。这是基于意见的领域,只要你认为它是可以维护的,没关系。

  • 这里有许多可能的解决方案,其中一个是
    ISettingsManager
    ,允许跨任何将其作为依赖项的服务实时访问设置


  • 1.Everything=应用程序任何部分中需要的每个依赖项,因为直接使用new或调用容器是不好的做法。2. <在这种情况下,code>ISettingsManager是有意义的,但您不需要手动实例化任何依赖项。IoC容器应该自己创建并注入任何依赖项。那么,假设您有一个无参数的ctor的
    IDependency
    ,以及将此依赖项作为参数的
    IService
    。如果在IoC容器中注册这两个的实现,则在
    Main
    方法中调用
    container.Resolve
    将返回
    iSeries
    -IoC将在引擎盖下为您构建
    IDependency
    。唯一需要的
    是创建容器本身。很抱歉,我没有正确解释。我理解IoC容器的概念,但是当您不在根目录(
    Main
    method)中时,我不知道如何使用它(不调用它)。例如,如果
    main窗口
    打开一个
    SettingsWindow
    ,它应该会收到一个实例。如果它打开100个不同的窗口,它应该会收到所有窗口的实例(间接地,它们的所有依赖项都将由IoC容器实例化),因为它“不允许”使用IoC容器或
    new
    关键字。这太疯狂了!。是的,那太疯狂了。IoC容器不是代码之神。如果您打开一个新窗口-这需要一个新的窗口实例。
    main窗口
    实例化一个新的
    设置Swindow
    ,这是一个完美的工厂设计模式的地方-您将有一个
    iWindows工厂
    注入您的
    main窗口
    (或服务处理窗口打开)使用方法
    CreateSettingsWindow
    返回
    SettingsWindow
    。工厂是你隐藏新关键字调用的地方。我喜欢你的解决方案,但我还有一个问题。IWindowFactory的实现必须接收对IoC容器(或其抽象)的引用,以解决新窗口的依赖关系。在使用工厂模式时,是否可以注入和使用IoC容器?
    public class Launcher : ILauncher
    {
        public Launcher(
            ILockService lockService,
            IAppRunnerService appRunnerService,
            IFileSyncService fileSyncService
            )
        {
            LockService = lockService;
            AppRunnerService = appRunnerService;
            FileSyncService = fileSyncService;
        }
    
        public ILockService LockService { get; }
        public IAppRunnerService AppRunnerService { get; }
        public IFileSyncService FileSyncService { get; }
    
        public void Run()
        {
            //TODO check lock + adquire lock
            //TODO Sinchronize file
            //TODO Subscribe to the IAppRunnerService.OnStop event 
            //TODO Start app through IAppRunnerService.Run method
        }
    }