【问题标题】:In Azure API for VM, is there a way to define many existing data disks with one method?在 Azure API for VM 中,有没有一种方法可以用一种方法定义多个现有数据磁盘?
【发布时间】:2019-12-30 16:17:20
【问题描述】:

我有一段流畅的 C# 代码:

如果我知道存在多少个磁盘,语法将是:

    var tempVM = await azure.VirtualMachines.Define(targetVMName)
        .WithRegion(vm.Region)
        .WithExistingResourceGroup(targetResourceGroupName)
        .WithNewPrimaryNetworkInterface(nicDefinitions[0])
        .WithSpecializedOSDisk(disks[0], disks[0].OSType.Value)
        .WithSize(vm.Size)
        .WithTags(tags)
        .WithExistingDataDisk(d[0]) <<<<<<<
        .WithExistingDataDisk(d[1]) <<<<<<<
        .WithExistingDataDisk(d[2]) <<<<<<<
        .WithExistingDataDisk(d[3]) <<<<<<<
        .CreateAsync();

我可能要添加 0 个或更多数据磁盘。是否有流畅的语法来支持 0 个或更多磁盘?

【问题讨论】:

  • 这取决于库。您在 Azure 中使用什么库?
  • 也许重新设计以将数据磁盘作为一个单独的实体在 0 对多的关系上
  • @Robert 我实际上以为是他自己写的。我的坏。
  • Is there a fluent syntax to support 0 or more disks ? -- There doesn't appear to be.
  • Fluent API 不是魔术,也不是“好的”实践。有时它们会有所帮助,有时它们会使调试变得痛苦。在许多情况下,它们只是返回原始接口的扩展方法。您可以轻松创建自己的扩展方法,将磁盘的IEnumerable&lt;&gt; 添加到定义中并返回它

标签: c# azure fluent azure-sdk-.net


【解决方案1】:

假设这是在一个名为IWithManagedCreate 的接口上使用扩展方法,你有这个方法:

public static IWithManagedCreate WithExistingDataDisk(this IWithManagedCreate vm, IDisk disk)
{
    // ...      
    return vm; 
}

您可以简单地使用 params IDisk[] 重载添加自己的扩展方法:

public static IWithManagedCreate WithExistingDataDisks(this IWithManagedCreate vm, params IDisk[] disks)
{
    foreach (var disk in disks)
    {
        vm = vm.WithExistingDataDisk(disk);
    }
    return vm; 
}

然后这样称呼它:

    .WithTags(tags)
    .WithExistingDataDisks(d) // passing the array containing 0 or more disks
    .CreateAsync();

所以,回答这个问题,不,流畅的语法没什么特别的,只是一个方法调用链。当你链接方法调用时(通过让每个方法返回一些你可以调用更多方法的东西),你不能让它们有条件;您可以创建一个方法,但是如上所示不执行任何操作。当你用一个空数组调用它时,什么都不会发生。

【讨论】:

    【解决方案2】:

    WithExistingDataDiskIWithManagedDataDisk 接口中声明。

    此接口不提供任何方法来一次调用添加多个现有的IDisk

    无论如何,您可以将它实现为这样的扩展方法:

    public static class WithManagedDataDiskExtensions
    {
        // allow to manually specify many disks to add
        public static IWithManagedDataDisk WithExistingDataDisks(this IWithManagedDataDisk self, params IDisk[] disks)
        {
            return self.WithExistingDataDisks((IEnumerable<IDisk>) disks);
        }
    
        // allow to add an enumerable of many disks
        public static IWithManagedDataDisk WithExistingDataDisks(this IWithManagedDataDisk self, IEnumerable<IDisk> disks)
        {
            foreach (var disk in disks)
                self = self.WithExistingDataDisk(disk);
    
            return self;
        }
    }
    

    并像这样使用它:

    var tempVM = await azure.VirtualMachines.Define(targetVMName)
        .WithRegion(vm.Region)
        .WithExistingResourceGroup(targetResourceGroupName)
        .WithNewPrimaryNetworkInterface(nicDefinitions[0])
        .WithSpecializedOSDisk(disks[0], disks[0].OSType.Value)
        .WithSize(vm.Size)
        .WithTags(tags)
        .WithExistingDataDisks(d[0], d[1], d[2], d[3])
      //.WithExistingDataDisks(d)
        .CreateAsync();
    

    【讨论】:

    • 您可以使用IEnumerable&lt;IDisk&gt; 代替params IDisk[] 并直接传递d
    • @PanagiotisKanavos, d 不一定是数组,最好的选择是同时拥有两个扩展名。
    【解决方案3】:

    通常在流畅的 API 中,您可以在循环中使用赋值,如下所示:

       var expTempVM = azure.VirtualMachines.Define(targetVMName)
            .WithRegion(vm.Region)
            .WithExistingResourceGroup(targetResourceGroupName)
            .WithNewPrimaryNetworkInterface(nicDefinitions[0])
            .WithSpecializedOSDisk(disks[0], disks[0].OSType.Value)
            .WithSize(vm.Size)
            .WithTags(tags);
    
        foreach (var d in disks)
        {
          expTempVM = expTempVM.WithExistingDataDisk(d);
        }
    
        var tempVM = await expTempVM.CreateAsync();
    

    Fluent API 的基本设计是每个方法返回其操作的相同类型。

    如果你能做到这一点,你还可以定义自己的扩展方法,.WithExistingDataDisks 或类似的。

    【讨论】:

    • 是的,但是WithTags() 可能会返回一个与WithExistingDataDisk()CreateAsync() 返回的类型不可分配的类型,因此您可能需要更多的中间变量来存储结果,并将控制流放在一个流利的块是一种击败首先拥有流利语法的目的......
    猜你喜欢
    • 2020-01-21
    • 1970-01-01
    • 2019-08-29
    • 2022-06-11
    • 2013-06-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多