【问题标题】:How do I instantiate a class with a constructor?如何使用构造函数实例化一个类?
【发布时间】:2022-01-21 09:44:24
【问题描述】:

我希望能够使用static void Main 方法在我的控制台应用程序中使用我的StartUp 类运行我的RunApp 方法。问题是我在 StartUp 类中使用依赖注入和构造函数来创建具有方法的其他类的实例。但我不知道如何继续,所以我可以在静态 void Main 中使用我的 RunApp 方法。

我试过用

StartUp s = new StartUp();
s.RunApp();

但是好像不行,我得有参数才能输入。

启动类

public class StartUp : IStartUp
{
    private readonly AddCustomer _addCustomer;
    private readonly Booking _booking;
    private readonly GetCustomer _getCustomer;
    private readonly Service _service;

    public StartUp(
        AddCustomer addCustomer,
        Booking booking,
        GetCustomer getCustomer,
        Service service)
    {
        _addCustomer = addCustomer;
        _booking = booking;
        _getCustomer = getCustomer;
        _service = service;
    }

    public void RunApp()
    {
        Console.WriteLine(
            "Hi! Welcome to Kennel GoldenRetriver. What would you like to do?");
        Console.WriteLine("Press 1 to register a new customer and dog");
        Console.WriteLine("Press 2 to show all customers");
        Console.WriteLine("Press 3 to get all dogs");
        Console.WriteLine("Press 4 to show customers and thier related dogs");
        Console.WriteLine("Press 5 to leave dog on service");
        Console.WriteLine("Press 6 to show all dogs on service");
        Console.WriteLine("Press 7 to get your dog from service");

        bool isNumber = int.TryParse(Console.ReadLine(), out int start);

        if (isNumber)
        {
            switch (start)
            {
                case 1:
                    _addCustomer.AddCustomers();
                    break;
                case 2:
                    _getCustomer.GetCustomers();
                    break;
                case 3:
                    _getCustomer.GetDogs();
                    break;
                case 4:
                    _getCustomer.GetRelatedCustomerToDog();
                    break;
                case 5:
                    _booking.AddBooking();
                    _service.AddService();
                    break;
                case 6:
                    _service.AddService();
                    break;
                case 7:
                    _service.DeleteFromService();
                    break;
                default:
                    Console.WriteLine("Please enter valid number");
                    break;
            }
        }
        else
        {
            Console.WriteLine("Enter a number");
        }
    }
}

我的主要方法

class Program 
{
    static void Main(string[] args)
    {
        StartUp s = new StartUp();
        s.RunApp();
    }
}

【问题讨论】:

  • 如果你想使用依赖注入,你必须随时提交。您可以自己创建依赖项(通过相同的规则实例化所有类)并将它们传递给构造函数。在不手动解决依赖关系的情况下,您还希望该类如何正常运行?
  • 您的依赖注入到底是在哪里设置的?如果在实例化StartUp 并调用RunApp 之前将服务添加到服务集合中,则可以简单地从服务提供者处检索StartUp 类并使用该实例调用RunApp
  • 感谢您的回复。我的想法是我应该在 StartUp 中实例化我需要的所有类。这就是我使用 Dependecy Injection 来实现所有功能并能够使用它们的地方。然后我只希望能够在 Static Void Main 方法中运行 RunApp,以便我可以运行程序本身。
  • DI 是一个笼统的术语,可能会引起一些混淆,因为我们过去称为 IoC 容器的职责是通过注入它们来满足依赖关系已经有点消失了,我们只是将其称为 DI现在,IoC/injector 的存在被隐藏了。您安排的确实是 DI 设置,因为 StartUp 具有注入的依赖项(通过构造函数),但似乎没有任何 IoC 设置,而且您似乎没有在自己的代码中手动注入它们。为此我预计你的问题会引起一些不解。或许可以解释一下 DI 对你意味着什么
  • @Daniel 阅读了这个blog.ploeh.dk/2014/06/10/pure-di

标签: c# asp.net dependency-injection


【解决方案1】:

主题类需要满足其所有依赖项才能按需要进行初始化。

所以要么通过Pure DI提供它们

class Program {
    static void Main(string[] args) {
        //...assuming the dependencies don't have dependencies themselves.
        AddCustomer addCustomer = new();
        Booking booking = new();
        GetCustomer getCustomer = new();
        Service service = new();
        
        StartUp s = new StartUp(addCustomer, booking, getCustomer, service);
        s.RunApp();
    }
}

或通过控制反转 (IoC) 容器来完成初始化和注入所有已注册依赖项的繁重工作。

使用默认 .Net Core 容器的简单示例

class Program {
    static void Main(string[] args) {
        IServiceProvider services = new ServiceCollection()
            .AddTransient<AddCustomer>()
            .AddTransient<Booking>()
            .AddTransient<GetCustomer>()
            .AddTransient<Service>()
            .AddTransient<StartUp>()
            .BuildServiceProvider();
        
        StartUp s = services.GetService<StartUp>();
        s.RunApp();
    }
}

在过于简化的 Pure DI 示例中,如果这些依赖项中的任何一个具有显式依赖项,那么也需要满足这些依赖项,以便在初始化主题类型时所有要求都可用。

您可以根据程序的复杂性和规模做出选择。

【讨论】:

  • 谢谢这是我正在寻找的答案!:)。但是,在我的 GetCustomer 中,我使用 Ef 核心,然后像在 StartUp 中那样使用 DI 来访问数据库。我在使用示例 2 时收到一条错误消息。其中显示“尝试激活 'KennelProgram.New.GetCustomer' 时无法解析类型 'KennelProgram.Data.ApplicationDbContext' 的服务”。我应该带更多东西让它工作吗?
  • 您需要AddDbContext&lt;ApplicationDbContext&gt; 到容器,以便它知道如何解析上下文在此处阅读docs.microsoft.com/en-us/aspnet/core/fundamentals/…
猜你喜欢
  • 2010-11-15
  • 1970-01-01
  • 1970-01-01
  • 2014-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-06
相关资源
最近更新 更多