WPF .Net Core 3.1 依赖 Injection/Service 参考问题

WPF .Net Core 3.1 Dependency Injection/Service Reference Question

我正在尝试从我的域 class

中引用 a_UserTenant 中的方法

这是最上面的部分:

public IServiceProvider Services { get; set; }
private readonly A_UserTenant a_UserTenant;
private readonly A_User a_User;
private string Username = null;

public Domain(string Username)
{
    InitializeComponent();
    this.Username = Username;
    UsernameTextbox.Text = Username;
    loading = new Loading.Loading();
    this.a_UserTenant = this.Services.GetRequiredService<A_UserTenant>();
    this.a_User = this.Services.GetRequiredService<A_User>();
}

这是我的App.Xaml

public IServiceProvider ServiceProvider { get; private set; }

public IConfiguration configuration { get; private set; }

protected override void OnStartup(StartupEventArgs e)
{
    var builder = new ConfigurationBuilder()
     .SetBasePath(Directory.GetCurrentDirectory())
     .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

    configuration = builder.Build();

    var serviceCollection = new ServiceCollection();
    ConfigureServices(serviceCollection);

    ServiceProvider = serviceCollection.BuildServiceProvider();

    var login = ServiceProvider.GetService<Login>();
    login.Show();
}

private void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddSingleton(configuration);
    LoadSDR_ManageWSControllers loadSDR_ManageWSControllers = new LoadSDR_ManageWSControllers();
    loadSDR_ManageWSControllers.Services(services);

    //Views
    services.AddTransient(typeof(Login));
    services.AddTransient(typeof(Domain));

}

现在的问题是我得到一个异常说 -

$exception {"Value cannot be null. (Parameter 'provider')"} System.ArgumentNullException

这是A_UserTenantclass的构造函数:

private readonly IConfiguration configuration;

public A_UserTenant(IConfiguration configuration)
{
    this.configuration = configuration;
}

我该如何解决这个问题?

编辑:

这是 A_UserTenant 中我想从我的域 class

中调用的方法之一
public UserTenant Get(string Id)
{
    RestClient client = new RestClient();
    var link = $"{link]}Directory/UserTenant/Get";
    var username = uname;
    var password = upw;
    client.BaseUrl = new Uri(link);
    client.Authenticator = new HttpBasicAuthenticator(username, password);
    RestRequest request = new RestRequest();
    request.AddParameter("Id", Id);
    request.Method = Method.GET;
    var res = client.Execute(request);
    if (res.StatusCode == System.Net.HttpStatusCode.OK)
    {
        return JsonConvert.DeserializeObject<UserTenant>(res.Content);
    }
    else
    {
        return null;
    }
}

这是我目前从另一个 class 导航到域 class 的方式:

Domain domain = new Domain(Username);
domain.Show();
this.Close();

如果您想在 WPF 中使用 .Net Core 依赖注入,为此您可以使用反射。例如通过其接口获取 运行 服务类型:

var interfaceType = typeof(IServiceProvider );
var services = Assembly.GetExecutingAssembly().GetTypes().Where(w => interfaceType.IsAssignableFrom(w)).ToList();

然后您可以使用 Activator.CreateInstance(<your service>) as <Service class>;

创建实例

根据你的问题,你正在注册 Domain 作为一项服务;

services.AddTransient(typeof(Domain));

但是你的构造函数暗示调用者是直接调用new,而不是从服务提供者那里获取实例;

public Domain(string Username) {...}

// maybe the caller looks like this?
var domain = new Domain(username);

正确设计会有点棘手。

您希望每个服务构造函数明确列出实际需要的服务,这样您就不会落入“服务定位器”反模式。

但是您不希望每个调用者都知道这些依赖关系。

您有多种选择来混合服务依赖项和参数。您可以将参数分配给实例方法。然后也许将所有内容封装在一个静态方法中;

public class Domain{
    private Domain(A_UserTenant a_UserTenant, A_User a_user) {...}
    private void SetUsername(string Username) {...}

    public static Domain Factory(IServiceProvider provider, string Username) 
    {
        var domain = services.GetRequiredServce<Domain>();
        domain.SetUsername(username);
        return domain;
    }
}

var domain = Domain.Factory(services, username);

或者您可以将表单从服务集合中删除,而只在新服务中注册依赖项 class;

public Domain(string Username, DomainDependencies dependencies) {...}

var domain = new Domain(
    username,
    services.GetRequiredService<DomainDependencies>()
);

无论哪种方式,您至少需要传递 IServiceProvider

依赖注入系统需要所有构造服务所需的信息,提前在ConfigureService方法中定义。在这种情况下这是不可能的,因为您的 Domain class 需要构造一个字符串。您可以创建某种具有 CreateDomain(string name) 方法的 IDomainService 并注入它。