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 并注入它。
我正在尝试从我的域 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 并注入它。