为什么要在类里实例化自身,请参考如下文章:
比如上位机需要做Modbus的通信.B/S架构,事先不知道有多少个链接.有需要是时候才实例化并保存通信连接...
public sealed class HoldingRegisters : ModbusTypeAbstract<ushort[]>
{
public static HoldingRegisters Instance { get; } = new HoldingRegisters();
//static HoldingRegisters(){}
private HoldingRegisters(){}
public override ushort[] Read(request req)
{
return GetOrAddConnection(req.connectiontype, req.destination)?.ReadHoldingRegisters(req.slaveid, req.address, req.count);
}
public override void Write(writerequest<ushort[]> wreq)
{
GetOrAddConnection(wreq.connectiontype,wreq.destination)?.WriteMultipleRegisters(wreq.slaveid, wreq.address, wreq.data);
}
}
public abstract class ModbusTypeAbstract<T> : IModbusType<T>
{
ConcurrentDictionary<string, IModbusMaster> connections = new ConcurrentDictionary<string, IModbusMaster>();
public abstract T Read(request req);
public abstract void Write(writerequest<T> wreq);
public virtual void ConnCount()
{
foreach (var conn in connections)
{
Console.WriteLine($"{ conn.Key } {conn.Value}");
}
}
/// <summary>
/// 验证IP连接字符串
/// </summary>
/// <param name="conn">IP连接字符串</param>
/// <param name="ip"></param>
/// <param name="port"></param>
/// <returns></returns>
private bool verifyIPConnectionString(string conn, out IPAddress ip, out int port)
{
port = 0;
ip = null;
var connectionarray = conn.Split(':');
if (connectionarray.Length != 2)
{
return false;
}
if (!int.TryParse(connectionarray[1], out port))
{
return false;
}
if (!IPAddress.TryParse(connectionarray[0], out ip))
{
return false;
}
return true;
}
protected IModbusMaster GetOrAddConnection(ConnectionType ctype, string conn)
{
switch (ctype)
{
case ConnectionType.SERIALRTU:
return connections.GetOrAdd(conn, (arg) =>
{
return ModbusSerialMaster.CreateRtu(new SerialPort(conn));
});
case ConnectionType.SERIALASCII:
return connections.GetOrAdd(conn, (arg) =>
{
return ModbusSerialMaster.CreateAscii(new SerialPort(conn));
});
case ConnectionType.TCP:
int port; IPAddress ip;
if (!verifyIPConnectionString(conn, out ip, out port))
{
return null;
}
return connections.GetOrAdd(conn, (arg) =>
{
return ModbusIpMaster.CreateIp(new TcpClient(ip.ToString(), port));
});
}
return null;
}
}
}
没有通信请求时,没有实例化通信连接
有个通信请求时候
只要是相同的IP和端口就不会新建连接
不同的IP和端口时:
目的是减少同一个类型new对象的次数。