【问题标题】:C# Async (Factory) Methods & LINQ [closed]C# 异步(工厂)方法和 LINQ [关闭]
【发布时间】:2017-12-31 14:56:49
【问题描述】:

我正在寻找一种合适的方式来设计我的代码。我有一个按以下方式创建的设备列表:

public void LoadDevices()
{
     using (XmlReader xmlRdr = new XmlTextReader(deviceConfigPath))
         deviceList = (from deviceElem in XDocument.Load(xmlRdr).Element("devices").Elements("device")
                 where (string)deviceElem.Attribute("type") == "mks247"
                 select (SmartCatDeviceBase)new mks247Device(
                    (string)deviceElem.Attribute("ip"),
                    (string)deviceElem.Attribute("name"),
                    (string)deviceElem.Attribute("id"),
                    (bool)deviceElem.Attribute("autoconnect")
                     )).ToList();
}

必须对 SmartCatDeviceBase 进行类型转换,因为我有更多不同类型的设备(具有相同的基类)进入该列表。

现在的问题是“自动连接”:它需要设备打开异步网络连接,这不应该在构造函数中完成 (as Stephen Cleary states here)。

因此我想求助于某种类似工厂的东西:

private async Task<SmartCatDeviceBase> Createmks247DeviceAsync(string host, string name, string id, bool autoconnect = true)
    {
        mks247Device dev = new mks247Device(host, name, id); // Now without the autoconnect, that shouldn't be in the constructor.
        // Connect.
        if (autoconnect)
        {
            bool connected = await dev.ConnectAsync();
            // Begin to poll for data.
            dev.BeginPolling();
        }
        return dev;  
    }

所以问题是:我怎样才能使该代码工作?因为使用 Createmks247DeviceAsync 而不是 new mks247Device() 在我的 LINQ 代码中不起作用:

“System.Threading.Tasks.Task”类型无法转换为“SmartCatDeviceBase”。

在select语句中使用await关键字也是不行的……

或者有没有其他方法可以正确地设计这样的代码?在构造函数中设置自动更正标志,然后稍后“从外部”连接似乎违反 OOP:当有自动连接选项时,我希望在我将其设置为 true 时反对自动创建...

提前非常感谢!新年快乐!

【问题讨论】:

  • 选择所有任务,然后等待Task.WhenAll连接它们。

标签: c# linq asynchronous constructor factory


【解决方案1】:

将方法一直转换为异步。

使用 Linq 选择所有任务,然后等待 Task.WhenAll 连接它们。

public async Task LoadDevicesAsync() {
     using (XmlReader xmlRdr = new XmlTextReader(deviceConfigPath)) {
         var getdeviceListTasks = (from deviceElem in XDocument.Load(xmlRdr).Element("devices").Elements("device")
                 where (string)deviceElem.Attribute("type") == "mks247"
                 select Createmks247DeviceAsync(
                    (string)deviceElem.Attribute("ip"),
                    (string)deviceElem.Attribute("name"),
                    (string)deviceElem.Attribute("id"),
                    (bool)deviceElem.Attribute("autoconnect")
                     ));
        var devices = await Task.WhenAll(getdeviceListTasks);
        deviceList = devices.ToList();
    }
}

【讨论】:

  • 谢谢,结果证明这是完美的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 1970-01-01
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
  • 2010-10-12
相关资源
最近更新 更多