如何避免一遍又一遍地创建同一个对象?

问题描述 投票:0回答:2

我继续处理我的 TCP 套接字,如今天早上提到的

我发现每次我通过这样的套接字发送消息时,套接字的数量都会不断增加。这仅仅意味着我不断创建和打开新的套接字,而不是重新使用已经打开的套接字。

在我的应用程序中,我有一个连接存储库,我只需要使用其中一个。但我担心我会不断地创造新的。做法是这样的:

public static class Repository { ... public static Conn GetByName(string name, ...) { return result = context.Set<Conn>().Where(o => o.Name == name).FirstOrDefault(); } } ... Conn Connection_For_Message = Repository.GetByName(request.ConnectionName, ...);
据我说:

    声明
  1. Repository
     的事实是 
    static
     会导致在内部创建一个对象。
  2. GetByName()
     方法执行 
    FirstOrDefault()
     方法的 
    Where()
     时,这会给出已经存在的对象,并且不会创建新对象。
现在我的印象是 1. 是正确的,但 2. 是错误的,因为

Connection Connection_For_Message

 
always 创建了一个对象的新实例。

我的印象是否正确?如果是,我该如何解决这个问题?我正在考虑将

Repository

 从静态类更改为单例,但我没有在 
ISingleton
 中找到 
System.Reflection
 或其他内容,或者我正在寻找完全错误的方向?

编辑:特此为Conn

类的构造函数的一部分:

public Conn(...) { ... TcpConnection = new TcpConnection(...); // in here a ... }

TcpConnection

类而言:

public class TcpConnection : IDisposable { public Socket _socket; ...
每次发送消息时,我都会通过 

GetByName()

 方法,我的调用堆栈如下所示:

My_Application.dll!TcpConnection.TcpConnection(...) Line 39 C# > My_Application.dll!Conn.Conn(...) Line 32 C# [External Code] My_Application.dll!ConnectionRepository.GetByName(string name, ...) Line 71 C#
标有 

>

 的行是构造函数,这确实证明 
GetByName()
 确实正在调用 
Conn
 构造函数。 (哦,为什么 
GetByName()
 方法和构造函数之间有“外部代码”?)

再次编辑:我已成功显示外部代码,特此选中“显示外部代码”的调用堆栈:

> My_Application.dll!TcpConnection.TcpConnection(...) Line 39 C# My_Application.dll!Conn.Conn(...) Line 32 C# [Native to Managed Transition] [Managed to Native Transition] System.Private.CoreLib.dll!System.Reflection.RuntimeConstructorInfo.Invoke(System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) C# System.Private.CoreLib.dll!System.RuntimeType.CreateInstanceImpl(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture) C# System.Private.CoreLib.dll!System.Activator.CreateInstance(System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) C# Castle.Core.dll!Castle.DynamicProxy.ProxyGenerator.CreateClassProxyInstance(System.Type proxyType, System.Collections.Generic.List<object> proxyArguments, System.Type classToProxy, object[] constructorArguments) C# [Lightweight Function] Microsoft.EntityFrameworkCore.Relational.dll!Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable<Conn>.Enumerator.MoveNext() C# System.Linq.dll!System.Linq.Enumerable.TryGetSingle<Conn>(System.Collections.Generic.IEnumerable<Conn> source, out bool found) C# [Lightweight Function] System.Linq.Queryable.dll!System.Linq.Queryable.FirstOrDefault<Conn>(System.Linq.IQueryable<Conn> source) C# My_Application.dll!ConnectionRepository.GetByName(string name, ...) Line 71 C#
    
c# scope static singleton callstack
2个回答
6
投票
您正在使用实体框架查询数据库以获取 Conn(正如我们从调用堆栈中看到的)。数据库当然不能存储TCP连接之类的东西。每次执行查询时,都会返回 Conn 的新实例(从技术上讲,它可以从缓存返回,但不会改变情况),尽管它代表相同的数据库行。在代表数据库条目的类的构造函数中创建 TCP 客户端不是一个好主意。

您可以使用

ConcurrentDictionary<string, TcpConnection>

 以线程安全的方式管理您的连接。


0
投票
使用 lambda,您可以在对象内查找类似的变量以获取散列变量或 PK(主键)。

PK是否应该是相同的跳过创建。

这样我们就可以确保我们不会使用设置的 PK 创建现有对象的新副本。

Var oldOjbect = context.object.firstordefault(o => o.pk == input.pk ) if (oldobject == null) { oldobject = new object { object.name = input.name} context.object.add(oldobject) context.SaveChanges(); }
看起来

TcpConnection = new TcpConnection(...)

你总是在建立新的联系?为什么不寻找以前的连接呢?使用 lambda 搜索 tcpconnection 的 PK

© www.soinside.com 2019 - 2024. All rights reserved.