我有以下类定义:
public class A {
private readonly B _b;
public A (B b){ _b = b; }
}
public class B {
private readonly C _c;
public B (C c) { _c = c; }
}
public class C {
public string IP;
}
以下注册:
services.AddSingleton<A>();
services.AddSingleton<B>();
services.AddScoped<C>(a => {
var accessor = a.GetService<Microsoft.AspNetCore.Http.IHttpContextAccessor>();
var header = accessor.HttpContext.Request.Headers;
return new C { IP = header["X_FORWARDED_FOR"] };
});
C.IP是一样的,
我希望它为每个客户端用户更改,而A B是单例。
我怎样才能做到这一点?
答案 0 :(得分:1)
有多种方法可以解决这个问题,但最优雅的方法如下。您只需将public class C {
private IHttpContextAccessor _accessor;
public C(IHttpContextAccessor accessor) { _accessor = accessor; }
public string IP => accessor.HttpContext.Request.Headers["X_FORWARDED_FOR"];
}
更改为:
IHttpContextAccessor
HttpContext
是ASP.NET Core中的单例,调用其HttpContext
属性将始终返回当前请求的C
。这允许services.AddSingleton<A>();
services.AddSingleton<B>();
services.AddSingleton<C>();
成为无国籍和单身。
这使您可以将注册简化为以下内容:
C
如果在不依赖于ASP.NET的程序集中定义IC
(例如业务层),这可能会给您带来问题。
通过为C
引入抽象B
并让IC
取决于public interface IC { }
public class B {
private readonly IC _c;
public B (IC c) { _c = c; }
}
,可以优雅地解决此问题:
IC
这样我们就可以将B
放在应用程序的基础层中(因此C
可以访问它)并将IHttpContextAccessor
实现移到Composition Root可以依赖public class C : IC {
private readonly IHttpContextAccessor _accessor;
public C(IHttpContextAccessor accessor) { _accessor = accessor; }
public string IP => accessor.HttpContext.Request.Headers["X_FORWARDED_FOR"];
}
的应用程序。
C
为此,您需要将services.AddSingleton<IC, C>();
的注册更改为:
Stream stream = client.GetStream();
StreamWriter sw = new StreamWriter(client.GetStream(), Encoding.ASCII);
StreamReader sr = new StreamReader(client.GetStream(), Encoding.ASCII);
else if (args.Length == 2)
{
while (args[1] != response)
{
// response = sr.ReadLine();
if (args[1] != response)
{
// this is what should be put in sw.write for the updated database entry
// <name><space><location><CR><LF>
// cssbct + " " + "is in fenner", so "cssbct location has changed"
// args[0] + " " + response
// response is now what the arg is
response = args[1];
// write the new response so that it will be sent to the server
sw.WriteLine(args[0] + " " + response);
// send it to the server
sw.Flush();
// write out the args and that the location has changed
// Console.WriteLine(args[0] + " " + " location changed to be" + " " + response);
// Just testing what the response should be
Console.WriteLine(args[0] + " " + response);
string Response2 = "";
// read the response from the server
Response2 = sr.ReadLine();
// if it equals "OK" do this
if (Response2 == "OK")
{
// drops connection to the server
// probably not what is needed but look at later date
Console.WriteLine(response);
Console.WriteLine("Client connection closed");
client.Close();
}
if (sr.EndOfStream)
{
Console.WriteLine("End of stream has been reached");
}