Avoiding 'new' in IOC

Hello, I am learning about dependency injection and one of the things said to avoid is using new in the constructor. How can I avoid doing stuff like this:
private readonly ILogger<DowntimeClient> _logger;
private readonly PipeAsync _pipeAsync;
private readonly Helper _helper;

private TcpClient _sendingClient;

private DowntimeClient(ILogger<DowntimeClient> logger, PipeAsync pipeAsync, Helper helper)
{
_logger = logger;
_pipeAsync = pipeAsync;
_helper = helper;
_sendingClient = new TcpClient();
}
private readonly ILogger<DowntimeClient> _logger;
private readonly PipeAsync _pipeAsync;
private readonly Helper _helper;

private TcpClient _sendingClient;

private DowntimeClient(ILogger<DowntimeClient> logger, PipeAsync pipeAsync, Helper helper)
{
_logger = logger;
_pipeAsync = pipeAsync;
_helper = helper;
_sendingClient = new TcpClient();
}
where I need _sendingClient throughout multiple methods in the class? Thanks!
43 Replies
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
So I should inject TcpClient in the constructor? Which means registering it in the DI Problem is, what about stuff like a List
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
What if it were a string? Would I need a wrapper for that as well
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
Well the TcpClient part isn't as big of a deal The main problem is where I need to initialize a ConcurrentDictionary<int, TcpClient> And then it is used in multiple methods in the class That one I can't seem to wrap my head around
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
I wish I could but I cannot upload to github I think I will need tor research more about holding state Or just use factory Do you by chance have any resources on this topic which I can read
mindhardt
mindhardt2y ago
Usually things like HttpClient/TcpClient or DbContext are either Transient/Scoped or injected as factories of themselves
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
FusedQyou
FusedQyou2y ago
Not sure how a simple question can turn in such a discussion 😆 What you are looking for is injecting your TcpClient as a transient service, same as how you (probably) injected DowntimeClient. That said, IMO having a new keyword inside an injected class is really not a bad thing in cases, but your TcpClient does sound like a dependency you should define.
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
MODiX
MODiX2y ago
Determinism#3334
The main problem is where I need to initialize a ConcurrentDictionary<int, TcpClient>
Quoted by
<@!689473681302224947> from #Avoiding 'new' in IOC (click here)
React with ❌ to remove this embed.
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
TcpClient implements IDisposable which leaks though Wouldn't want to make it transient I thought
MODiX
MODiX2y ago
Determinism#3334
The main problem is where I need to initialize a ConcurrentDictionary<int, TcpClient>
Quoted by
<@!689473681302224947> from #Avoiding 'new' in IOC (click here)
React with ❌ to remove this embed.
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
FusedQyou
FusedQyou2y ago
No it doesn't DI will dispose of it properly
Determinism
DeterminismOP2y ago
Unfortunately I cannot upload my github, sorry, this was meant to be a basic question at first as I didn't really understand how in depth it was at the time
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
That's what I was thinking My case is very basic
private async ValueTask WriteDowntimeMessageToStandController(ReadOnlySequence<byte> buffer,
CancellationToken cancellationToken)
{
if (!_tcpClient.Connected)
{
try
{
await _tcpClient.ConnectAsync(_connectionsOptions.StandControllerIp, _connectionsOptions.DataCollectorPort, cancellationToken); // reusing this port
_logger.LogInformation("Connected to the stand controller on {_standControllerIp}:{_standControllerPort}",
_connectionsOptions.StandControllerIp, _connectionsOptions.StandControllerPort);
}
catch (Exception ex)
{
_logger.LogError(ex, "WriteDowntimeMessageToStandController-Exception");
}
}

try
{
foreach (var segment in buffer)
{
var stream = _tcpClient.GetStream();

await stream.WriteAsync(segment, cancellationToken);
}
}
catch (Exception ex)
{
_logger.LogError(ex,
"Error sending downtime to the stand controller at {_standControllerIp}.",
_connectionsOptions.StandControllerIp);

_tcpClient.Close();
}
}
private async ValueTask WriteDowntimeMessageToStandController(ReadOnlySequence<byte> buffer,
CancellationToken cancellationToken)
{
if (!_tcpClient.Connected)
{
try
{
await _tcpClient.ConnectAsync(_connectionsOptions.StandControllerIp, _connectionsOptions.DataCollectorPort, cancellationToken); // reusing this port
_logger.LogInformation("Connected to the stand controller on {_standControllerIp}:{_standControllerPort}",
_connectionsOptions.StandControllerIp, _connectionsOptions.StandControllerPort);
}
catch (Exception ex)
{
_logger.LogError(ex, "WriteDowntimeMessageToStandController-Exception");
}
}

try
{
foreach (var segment in buffer)
{
var stream = _tcpClient.GetStream();

await stream.WriteAsync(segment, cancellationToken);
}
}
catch (Exception ex)
{
_logger.LogError(ex,
"Error sending downtime to the stand controller at {_standControllerIp}.",
_connectionsOptions.StandControllerIp);

_tcpClient.Close();
}
}
I'm only using it in this method
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
That's what I would put in the repo That method is the only one that uses the TcpClient
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
I'm just initializing the TcpClient in the constructor
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
That's why I would want to do this
private async ValueTask WriteDowntimeMessageToStandController(ReadOnlySequence<byte> buffer,
CancellationToken cancellationToken)
{
if (!_tcpClient.Connected)
{
try
{
_tcpClient = new();
await _tcpClient.ConnectAsync(_connectionsOptions.StandControllerIp, _connectionsOptions.DataCollectorPort, cancellationToken); // reusing this port
_logger.LogInformation("Connected to the stand controller on {_standControllerIp}:{_standControllerPort}",
_connectionsOptions.StandControllerIp, _connectionsOptions.StandControllerPort);
}
catch (Exception ex)
{
_logger.LogError(ex, "WriteDowntimeMessageToStandController-Exception");
}
}

try
{
foreach (var segment in buffer)
{
var stream = _tcpClient.GetStream();

await stream.WriteAsync(segment, cancellationToken);
}
}
catch (Exception ex)
{
_logger.LogError(ex,
"Error sending downtime to the stand controller at {_standControllerIp}.",
_connectionsOptions.StandControllerIp);

_tcpClient.Close();
}
}
private async ValueTask WriteDowntimeMessageToStandController(ReadOnlySequence<byte> buffer,
CancellationToken cancellationToken)
{
if (!_tcpClient.Connected)
{
try
{
_tcpClient = new();
await _tcpClient.ConnectAsync(_connectionsOptions.StandControllerIp, _connectionsOptions.DataCollectorPort, cancellationToken); // reusing this port
_logger.LogInformation("Connected to the stand controller on {_standControllerIp}:{_standControllerPort}",
_connectionsOptions.StandControllerIp, _connectionsOptions.StandControllerPort);
}
catch (Exception ex)
{
_logger.LogError(ex, "WriteDowntimeMessageToStandController-Exception");
}
}

try
{
foreach (var segment in buffer)
{
var stream = _tcpClient.GetStream();

await stream.WriteAsync(segment, cancellationToken);
}
}
catch (Exception ex)
{
_logger.LogError(ex,
"Error sending downtime to the stand controller at {_standControllerIp}.",
_connectionsOptions.StandControllerIp);

_tcpClient.Close();
}
}
But I can't because I need to avoid new
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
Hastebin: Send and Save Text or Code Snippets for Free | Toptal®
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
Determinism
DeterminismOP2y ago
It actually is in a backgroundservice The GetStream on every loop was a mistype
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
Okay, thanks, so it should be fine for the ConcurrentDictionary as well then
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
Well I only use it in that one class Which implements BackgroundService
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
It's a different BackgroundService
Determinism
DeterminismOP2y ago
Hastebin: Send and Save Text or Code Snippets for Free | Toptal®
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
Why would it do that? the id is outside the loop
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Determinism
DeterminismOP2y ago
Np, thanks for looking over it
Want results from more Discord servers?
Add your server