委托(1)

本文介绍委托的基本概念及其实现原理,展示了如何使用委托将方法作为参数传递,并通过实例演示了委托链的构建与执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

委托的概念
委托实际上是类(一个貌似函数一样的类),我们已经使用函数指针很多年了——函数指针也被称为过程类型,但是它们的实现都不是类。它们是单独的函数指针的简单实例。委托是包含这些功能的类,委托类通过保留的列表来确定某些事物是否已经指派给了委托,这种算法可以理解为:“对于内部列表中的每一个回调函数,都调用函数”。委托除了支持回调函数外,还可以通过该列表来实现多播(委托链)。
说白了,就是我们把一批具有相同特征的方法,通过建立与具有同样相同特征的委托的一个实例来进行传递,以使其它地方能对这些方法进行调用。即把方法当作参数进行传递(浅显的认识,勿笑)。
 
初识委托
示例1:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
 
 
namespace MyDelegateTest
{
     ///<summary>
     ///说明:一个简单的委托示例
     ///作者:文野
     ///联系:stwyhm.cnblogs.com
     ///</summary>
 
     // 新建一个用以输出消息的委托
     public delegate void WriteMessage();
    
     public class WriteToWeb
     {
         // 一个输出消息的静态方法
         public static void StaticWrite()
         {
              HttpContext.Current.Response.Write("委托调用了一个静态方法。<br />");
         }
 
         // 一个输出消息的类实例方法
         public void Write()
         {
              HttpContext.Current.Response.Write("委托调用了一个类实例方法。<br />");
         }
     }
}
调用:
protected void Page_Load(object sender, EventArgs e)
    {
         // 新建一个委托,回调函数是一个静态方法
         WriteMessage wm = new WriteMessage(WriteToWeb.StaticWrite);
 
         WriteToWeb w = new WriteToWeb();
         // 新建一个委托并与加到先前建立的委托组成委托链,回调函数是一个类实例方法
         wm += new WriteMessage(w.Write);
 
         // 执行委托链上所有的回调函数
         wm();
    }
 
上面的示例程序首先建立了一个简单得不能再简单的用以输出的委托,下面的类中有两个与委托签名一致的方法(一个静态方法,一个类实例方法)。下面的调用过程首先建立了一个使用回调静态方法的委托,其后又建立了一个使用类实例方法的委托并与先前的委托组成了一个委托链,最后执行委托链上所有的方法。
由此可见,委托最简单的理解就是利用与方法签名一致的委托,可以把方法当作参数一样来传递,无论是静态方法还是类实例方法。
 
委托的秘密


从上面的类视图中我们看到,对委托的定义最终被编译成一个类,这个类中定义有4种方法:构造器,Invoke,BeginInvoke,EndInvoke。
所有的委托都继承自MulticastDelegate,而MulticastDelegate又继续至Delegate。这样我们定义的委托自然也就继承了MulticastDelegate的字段、属性和方法。在继承得到的所有成员中,有3个最重要的字段:
1、_target:指向调用回调函数时应该操作的对象。该字段用于实例方法的回调。
2、_methodPtr:一个内部的整数值,CLR用它来识别回调的方法。
3、_prev:指向另一个委托对象。
当编译器知道我们在构造的是一个委托时,它会分析源代码来确定要引用哪个对象和方法。其中对象引用会被传递给_target(对于静态方法,_target被置为null),一个特殊的标识方法的Int32值会被传递给_methodPtr,_prev在构造器中被置为null,它被用于在委托链中记录下一个委托的引用。
每个委托对象实际上是对方法及其调用操作的一个包装,MulticastDelegate中定义了两个只读属性,Target和Method,Target(其实就是前面的_target字段)属性返回一个方法回调时操作的对象的引用,Method属性返回一个标识回调方法的System.Reflection.MethodInfo对象。
 
<think>我们使用openstack-config命令来设置Cinder配置文件中的LVM后端参数。用户要求设置以下参数:1.volume_group=cinder-volumes2.iscsi_protocol=iscsi3.iscsi_helper=lioadm注意:这些参数都是在[lvm]配置节下设置的。步骤:1.确保已经创建了名为`cinder-volumes`的LVM卷组(如果尚未创建,需要先创建)。2.使用openstack-config命令设置参数。3.重启CinderVolume服务使配置生效。具体命令如下:</think>### 配置 Cinder LVM 后端参数 要使用 `openstack-config` 命令配置 Cinder LVM 后端,请执行以下命令序列: ```bash # 设置卷组名称 openstack-config --set /etc/cinder/cinder.conf lvm volume_group cinder-volumes # 设置 iSCSI 协议类型 openstack-config --set /etc/cinder/cinder.conf lvm iscsi_protocol iscsi # 设置 iSCSI 管理工具 openstack-config --set /etc/cinder/cinder.conf lvm iscsi_helper lioadm # 启用 LVM 后端(若未启用) openstack-config --set /etc/cinder/cinder.conf DEFAULT enabled_backends lvm # 重启服务使配置生效 systemctl restart openstack-cinder-volume target systemctl enable openstack-cinder-volume target ``` #### 参数说明: 1. **`volume_group = cinder-volumes`** - 指定 LVM 使用的卷组名称,必须与系统中已创建的卷组一致 - 创建卷组示例: ```bash pvcreate /dev/sdb # 创建物理卷 vgcreate cinder-volumes /dev/sdb # 创建卷组[^5] ``` 2. **`iscsi_protocol = iscsi`** - 定义 iSCSI 协议类型(默认为 iscsi) - 支持值:`iscsi`(标准协议)或 `iser`(RDMA 加速) 3. **`iscsi_helper = lioadm`** - 指定 iSCSI 目标管理工具 - 常用选项:`lioadm`(LIO 内核目标)或 `tgtadm`(TGT 用户空间目标) #### 验证配置: ```bash # 检查配置节 grep -A 5 '[lvm]' /etc/cinder/cinder.conf # 预期输出 [lvm] volume_group = cinder-volumes iscsi_protocol = iscsi iscsi_helper = lioadm ``` #### 创建 Cinder 用户和服务端点(若未配置): ```bash # 创建 cinder 用户 openstack user create --domain default --password CINDER_PASS cinder # 添加 admin 角色 openstack role add --project service --user cinder admin # 创建服务端点 openstack service create --name cinderv2 --description "OpenStack Block Storage" volumev2 openstack service create --name cinderv3 --description "OpenStack Block Storage" volumev3 ``` #### 注意事项: 1. **权限要求**:所有命令需以 root 权限执行 2. **服务依赖**:必须同时重启 `target` 服务(iSCSI 目标服务) 3. **空间验证**:执行 `vgs cinder-volumes` 确认卷组可用空间 4. **防火墙**:确保 iSCSI 端口(TCP 3260)在节点间可访问 [^1]: [OpenStack 官方存储指南](https://docs.openstack.org/cinder/latest/configuration/block-storage/backends.html) [^2]: [Cinder LVM 配置参考](https://docs.openstack.org/cinder/latest/configuration/block-storage/configuring-lvm-driver.html)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值