python之CMDB
浅谈ITIL
TIL即IT基础架构库(Information Technology Infrastructure Library, ITIL,信息技术基础架构库)由英国政府部门CCTA(Central Computing and Telecommunications Agency)在20世纪80年代末制订,现由英国商务部OGC(Office of Government Commerce)负责管理,主要适用于IT服务管理(ITSM)。ITIL为企业的IT服务管理实践提供了一个客观、严谨、可量化的标准和规范。
1、事件管理(Incident Management)
事故管理负责记录、归类和安排专家处理事故并监督整个处理过程直至事故得到解决和终止。事故管理的目的是在尽可能最小地影响客户和用户业务的情况下使IT系统恢复到服务级别协议所定义的服务级别。
2、问题管理(Problem Management)
问题管理是指通过调查和分析IT基础架构的薄弱环节、查明事故产生的潜在原因,并制定解决事故的方案和防止事故再次发生的措施,将由于问题和事故对业务产生的负面影响减小到最低的服务管理流程。与事故管理强调事故恢复的速度不同,问题管理强调的是找出事故产生的根源,从而制定恰当的解决方案或防止其再次发生的预防措施。
3、配置管理(Configuration Management)
配置管理是识别和确认系统的配置项,记录和报告配置项状态和变更请求,检验配置项的正确性和完整性等活动构成的过程,其目的是提供IT基础架构的逻辑模型,支持其它服务管理流程特别是变更管理和发布管理的运作。
4、变更管理(Change Management)
变更管理是指为在最短的中断时间内完成基础架构或服务的任一方面的变更而对其进行控制的服务管理流程。变更管理的目标是确保在变更实施过程中使用标准的方法和步骤,尽快地实施变更,以将由变更所导致的业务中断对业务的影响减小到最低。
5、发布管理(Release Management)
发布管理是指对经过测试后导入实际应用的新增或修改后的配置项进行分发和宣传的管理流程。发布管理以前又称为软件控制与分发
事件管理的目标是在不影响业务的情况下,尽可能快速的恢复服务,从而保证最佳的效率和服务的可持续性。事件管理流程的建立包括事件分类,确定事件的优先级和建立事件的升级机制。
问题管理是调查基础设施和所有可用信息,包括事件数据库,来确定引起事件发生的真正潜在原因,一起提供的服务中可能存在的故障。
配置管理的目标是:定义和控制服务与基础设施的部件,并保持准确的配置信息。
变更管理的目标是:以受控的方式,确保所有变更得到评估、批准、实施和评审。
发布管理的目标是:在实际运行环境的发布中,交付、分发并跟踪一个或多个变更。
服务台:服务台是IT部门和IT服务用户之间的单一联系点。它通过提供一个集中和专职的服务联系点促进了组织业务流程与服务管理基础架构集成。服务台的主要目标是协调客户(用户)和IT部门之间的联系,为IT服务运作提供支持,从而提高客户的满意度。
CMDB介绍
CMDB --Configuration Management Database 配置管理数据库, CMDB存储与管理企业IT架构中设备的各种配置信息,它与所有服务支持和服务交付流程都紧密相联,支持这些流程的运转、发挥配置信息的价值,同时依赖于相关流程保证数据的准确性。
- 整合是指能够充分利用来自其他数据源的信息,对CMDB中包含的记录源属性进行存取,将多个数据源合并至一个视图中,生成连同来自CMDB和其他数据源信息在内的报告;
- 调和能力是指通过对来自每个数据源的匹配字段进行对比,保证CMDB中的记录在多个数据源中没有重复现象,维持CMDB中每个配置项目数据源的完整性;自动调整流程使得初始实施、数据库管理员的手动运作和现场维护支持工作降至最低;
- 同步指确保CMDB中的信息能够反映联合数据源的更新情况,在联合数据源更新频率的基础上确定CMDB更新日程,按照经过批准的变更来更新 CMDB,找出未被批准的变更;
- 应用映射与可视化,说明应用间的关系并反应应用和其他组件之间的依存关系,了解变更造成的影响并帮助诊断问题。
CMDB 资产管理部分实现
需求
- 存储所有IT资产信息
- 数据可手动添加
- 硬件信息可自动收集
- 硬件信息可自动变更
- 可对其它系统灵活开放API
- API接口安全认证
立业之本:定义表结构
- 各种硬件都能存
- 资产变更有纪录
- 资产ID永不变
- 资产要有状态机
重中之重:接口设计好
- 可对内外灵活开放接口
- 接口定义要标准化
- 一定要提供排错依据
- 数据返回要标准
- 要能增删改查
- 所有异常要抓住
- 接口安全要注意
# -*- coding:utf-8 -*-
from django.db import models
from Wolf.models import UserProfile
# Create your models here. class Asset(models.Model):
asset_type_choices = (
('server', u'服务器'),
('switch', u'交换机'),
('router', u'路由器'),
('firewall', u'防火墙'),
('storage', u'存储设备'),
('NLB', u'负载均衡'),
('wireless', u'无线AP'),
('software', u'软件资产'),
('others', u'其它类'),
)
asset_type = models.CharField(u'资产类型', choices=asset_type_choices,max_length=64, default='server')
name = models.CharField(u'名字', max_length=64, unique=True)
sn = models.CharField(u'资产SN号', max_length=128, unique=True)
manufactory = models.ForeignKey('Manufactory', verbose_name=u'制造商', null=True, blank=True)
#model = models.ForeignKey('ProductModel', verbose_name=u'型号')
management_ip = models.GenericIPAddressField(u'管理IP', blank=True, null=True) contract = models.ForeignKey('Contract', verbose_name=u'合同', null=True, blank=True)
trade_date = models.DateField(u'购买时间', null=True, blank=True)
expire_date = models.DateField(u'过保修期', null=True, blank=True)
price = models.FloatField(u'价格',null=True, blank=True)
business_unit = models.ForeignKey('BusinessUnit', verbose_name=u'所属业务线', null=True, blank=True)
tags = models.ManyToManyField('Tag', verbose_name=u'标签', blank=True)
admin = models.ForeignKey(UserProfile, verbose_name=u'资产管理员', null=True, blank=True)
idc = models.ForeignKey('IDC', verbose_name=u'IDC机房', null=True, blank=True) #status = models.ForeignKey('Status', verbose_name = u'设备状态',default=1)
#Configuration = models.OneToOneField('Configuration',verbose_name='配置管理',blank=True,null=True) memo = models.TextField(u'备注', null=True, blank=True)
create_date = models.DateTimeField(blank=True, auto_now_add=True)
update_date = models.DateTimeField(blank=True, auto_now=True) class Meta:
verbose_name = '资产总表'
verbose_name_plural = "资产总表" def __str__(self):
return 'id:%s name:%s' % (self.id,self.name ) class Server(models.Model):
# server关联asset,反向关联,对于资产来说,是一对多关系
asset = models.OneToOneField('Asset',verbose_name=u'资产')
created_by_choices = (
('auto', 'Auto'),
('manual', 'Manual'),
)
created_by = models.CharField(choices=created_by_choices,max_length=32,
verbose_name=u'添加类型',default='auto') #auto: auto created, manual:created manually
hosted_on = models.ForeignKey('self',related_name='hosted_on_server',blank=True,null=True) #for vitural server
#sn = models.CharField(u'SN号',max_length=128)
#management_ip = models.CharField(u'管理IP',max_length=64,blank=True,null=True)
#manufactory = models.ForeignKey(verbose_name=u'制造商',max_length=128,null=True, blank=True)
model = models.CharField(u'型号',max_length=128,null=True, blank=True )
# 若有多个CPU,型号应该都是一致的,故没做ForeignKey #nic = models.ManyToManyField('NIC', verbose_name=u'网卡列表')
#disk
raid_type = models.CharField(u'raid类型',max_length=512, blank=True,null=True)
#physical_disk_driver = models.ManyToManyField('Disk', verbose_name=u'硬盘',blank=True,null=True)
#raid_adaptor = models.ManyToManyField('RaidAdaptor', verbose_name=u'Raid卡',blank=True,null=True)
#memory
#ram_capacity = models.IntegerField(u'内存总大小GB',blank=True)
#ram = models.ManyToManyField('Memory', verbose_name=u'内存配置',blank=True,null=True) os_type = models.CharField(u'操作系统类型',max_length=64, blank=True,null=True)
os_distribution =models.CharField(u'发型版本',max_length=64, blank=True,null=True)
os_release = models.CharField(u'操作系统版本',max_length=64, blank=True,null=True) create_date = models.DateTimeField(verbose_name=u'创建日期', blank=True, auto_now_add=True)
update_date = models.DateTimeField(verbose_name=u'更新日期', blank=True,null=True)
class Meta:
verbose_name = '服务器'
verbose_name_plural = "服务器"
#together = ["sn", "asset"] def __str__(self):
return '%s sn:%s' %(self.asset.name,self.asset.sn) class NetworkDevice(models.Model):
asset = models.OneToOneField('Asset')
vlan_ip = models.GenericIPAddressField(u'VlanIP',blank=True,null=True)
intranet_ip = models.GenericIPAddressField(u'内网IP',blank=True,null=True)
sn = models.CharField(u'SN号',max_length=128,unique=True)
#manufactory = models.CharField(verbose_name=u'制造商',max_length=128,null=True, blank=True)
model = models.CharField(u'型号',max_length=128,null=True, blank=True )
firmware = models.ForeignKey('Software',blank=True,null=True)
port_num = models.SmallIntegerField(u'端口个数',null=True, blank=True )
device_detail = models.TextField(u'设置详细配置',null=True, blank=True )
create_date = models.DateTimeField(verbose_name=u'创建日期',auto_now_add=True)
update_date = models.DateTimeField(verbose_name=u'更新日期',blank=True,null=True) class Meta:
verbose_name = '网络设备'
verbose_name_plural = "网络设备" class Software(models.Model):
#sn = models.CharField(u'SN号',max_length=64, unique=True)
os_types_choice = (
('linux', 'Linux'),
('windows', 'Windows'),
('network_firmware', 'Network Firmware'),
('software', 'Softwares'),
)
os_distribution_choices = (('windows','Windows'),
('centos','CentOS'),
('ubuntu', 'Ubuntu'))
type = models.CharField(u'软件类型', choices=os_types_choice, max_length=64,help_text=u'eg. GNU/Linux',default=1)
distribution = models.CharField(u'发型版本', choices=os_distribution_choices,max_length=32,default='windows')
version = models.CharField(u'软件/系统版本', max_length=64, help_text=u'eg. CentOS release 6.5 (Final)', unique=True)
language_choices = (('cn',u'中文'),
('en',u'英文'))
language = models.CharField(u'系统语言',choices = language_choices, default='cn',max_length=32)
#version = models.CharField(u'版本号', max_length=64,help_text=u'2.6.32-431.3.1.el6.x86_64' ) class Meta:
verbose_name = '软件/系统'
verbose_name_plural = "软件/系统" def __str__(self):
return self.version class CPU(models.Model):
asset = models.OneToOneField('Asset', verbose_name=u'资产')
cpu_model = models.CharField(u'CPU型号', max_length=128, blank=True)
cpu_count = models.SmallIntegerField(u'物理cpu个数')
cpu_core_count = models.SmallIntegerField(u'cpu核数')
memo = models.TextField(u'备注', null=True,blank=True)
create_date = models.DateTimeField(verbose_name=u'创建日期',auto_now_add=True)
update_date = models.DateTimeField(verbose_name=u'更新日期',blank=True,null=True) class Meta:
verbose_name = 'CPU部件'
verbose_name_plural = "CPU部件" def __str__(self):
return self.cpu_model class RAM(models.Model):
asset = models.ForeignKey('Asset', verbose_name=u'资产') # 各个模块都当做asset的一个部件处理
sn = models.CharField(u'SN号', max_length=128, blank=True,null=True)
model = models.CharField(u'内存型号', max_length=128)
slot = models.CharField(u'插槽', max_length=64)
capacity = models.IntegerField(u'内存大小(MB)')
memo = models.CharField(u'备注',max_length=128, blank=True,null=True)
create_date = models.DateTimeField(verbose_name=u'创建日期',blank=True, auto_now_add=True)
update_date = models.DateTimeField(verbose_name=u'更新日期',blank=True,null=True) class Meta:
verbose_name = 'RAM'
verbose_name_plural = "RAM"
unique_together = ("asset", "slot")
auto_create_fields = ['sn','slot','model','capacity'] def __str__(self):
return '%s:%s:%s' % (self.asset_id, self.slot, self.capacity) class Disk(models.Model):
asset = models.ForeignKey('Asset')
sn = models.CharField(u'SN号', max_length=128, blank=True,null=True)
slot = models.CharField(u'插槽位',max_length=64)
manufactory = models.CharField(u'制造商', max_length=64,blank=True,null=True)
model = models.CharField(u'磁盘型号', max_length=128,blank=True,null=True)
capacity = models.FloatField(u'磁盘容量GB')
disk_iface_choice = (
('SATA', 'SATA'),
('SAS', 'SAS'),
('SCSI', 'SCSI'),
('SSD', 'SSD'),
) iface_type = models.CharField(u'接口类型', max_length=64,choices=disk_iface_choice,default='SAS')
memo = models.TextField(u'备注', blank=True,null=True)
create_date = models.DateTimeField(verbose_name=u'创建日期',blank=True, auto_now_add=True)
update_date = models.DateTimeField(verbose_name=u'更新日期',blank=True,null=True) auto_create_fields = ['sn','slot','manufactory','model','capacity','iface_type'] class Meta:
unique_together = ("asset", "slot")
verbose_name = '硬盘'
verbose_name_plural = "硬盘" def __str__(self):
return '%s:slot:%s capacity:%s' % (self.asset_id,self.slot,self.capacity) class NIC(models.Model):
asset = models.ForeignKey('Asset')
name = models.CharField(u'网卡名', max_length=64, blank=True,null=True)
sn = models.CharField(u'SN号', max_length=128, blank=True,null=True)
model = models.CharField(u'网卡型号', max_length=128, blank=True,null=True)
macaddress = models.CharField(u'MAC', max_length=64,unique=True)
ipaddress = models.GenericIPAddressField(u'IP', blank=True,null=True)
netmask = models.CharField(u'掩码',max_length=64,blank=True,null=True)
bonding = models.CharField(u'绑定',max_length=64,blank=True,null=True)
memo = models.CharField(u'备注',max_length=128, blank=True,null=True)
create_date = models.DateTimeField(verbose_name=u'创建日期',blank=True, auto_now_add=True)
update_date = models.DateTimeField(verbose_name=u'更新日期',blank=True,null=True) class Meta:
verbose_name = u'网卡'
verbose_name_plural = u"网卡"
#unique_together = ("asset_id", "slot")
auto_create_fields = ['name','sn','model','macaddress','ipaddress','netmask','bonding'] def __str__(self):
return '%s:%s' % (self.asset_id, self.macaddress) class RaidAdaptor(models.Model):
asset = models.ForeignKey('Asset')
sn = models.CharField(u'SN号', max_length=128, blank=True,null=True)
slot = models.CharField(u'插口',max_length=64)
model = models.CharField(u'型号', max_length=64,blank=True,null=True)
memo = models.TextField(u'备注', blank=True,null=True)
create_date = models.DateTimeField(verbose_name=u'创建日期',blank=True, auto_now_add=True)
update_date = models.DateTimeField(verbose_name=u'更新日期',blank=True,null=True) class Meta:
unique_together = ("asset", "slot") def __str__(self):
return self.name class Manufactory(models.Model):
manufactory = models.CharField(u'厂商名称',max_length=64, unique=True)
support_num = models.CharField(u'支持电话',max_length=30,blank=True)
memo = models.CharField(u'备注',max_length=128,blank=True) class Meta:
verbose_name = '厂商'
verbose_name_plural = "厂商" def __str__(self):
return self.manufactory class BusinessUnit(models.Model):
parent_unit = models.ForeignKey('self',related_name='parent_level',blank=True,null=True)
name = models.CharField(u'业务线',max_length=64, unique=True) #contact = models.ForeignKey(UserProfile,default=None)
memo = models.CharField(u'备注',max_length=64, blank=True) class Meta:
verbose_name = '业务线'
verbose_name_plural = "业务线" def __str__(self):
return self.name class Contract(models.Model):
sn = models.CharField(u'合同号', max_length=128,unique=True)
name = models.CharField(u'合同名称', max_length=64 )
memo = models.TextField(u'备注', blank=True,null=True)
price = models.IntegerField(u'合同金额')
detail = models.TextField(u'合同详细',blank=True,null=True)
start_date = models.DateField(blank=True)
end_date = models.DateField(blank=True)
license_num = models.IntegerField(u'license数量',blank=True)
create_date = models.DateField(verbose_name=u'创建日期',auto_now_add=True)
update_date= models.DateField(verbose_name=u'更新日期',auto_now=True) class Meta:
verbose_name = '合同'
verbose_name_plural = "合同" def __str__(self):
return self.name class IDC(models.Model):
name = models.CharField(u'机房名称',max_length=64,unique=True)
memo = models.CharField(u'备注',max_length=128,blank=True,null=True) class Meta:
verbose_name = '机房'
verbose_name_plural = "机房" def __str__(self):
return self.name class Tag(models.Model):
name = models.CharField(u'标签名',max_length=32,unique=True )
creater = models.ForeignKey(UserProfile,verbose_name=u'创建人')
create_date = models.DateField(verbose_name=u'创建日期',auto_now_add=True) def __str__(self):
return self.name class EventLog(models.Model):
name = models.CharField(u'事件名称', max_length=100)
event_type_choices = (
(1,u'硬件变更'),
(2,u'新增配件'),
(3,u'设备下线'),
(4,u'设备上线'),
(5,u'定期维护'),
(6,u'业务上线\更新\变更'),
(7,u'其它'),
)
event_type = models.SmallIntegerField(u'事件类型', choices= event_type_choices)
asset = models.ForeignKey('Asset')
component = models.CharField('事件子项', max_length=255, blank=True,null=True)
detail = models.TextField(u'事件详情')
date = models.DateTimeField(u'事件时间', auto_now_add=True)
user = models.ForeignKey(UserProfile, verbose_name=u'事件源')
memo = models.TextField(u'备注', blank=True,null=True) def colored_event_type(self):
if self.event_type == 1:
cell_html = '<span style="background: orange;">%s</span>'
elif self.event_type == 2 :
cell_html = '<span style="background: yellowgreen;">%s</span>'
else:
cell_html = '<span >%s</span>'
return cell_html % self.get_event_type_display()
colored_event_type.allow_tags = True
colored_event_type.short_description = u'事件类型' class Meta:
verbose_name = '事件纪录'
verbose_name_plural = "事件纪录" def __str__(self):
return self.name class NewAssetApprovalZone(models.Model):
sn = models.CharField(u'资产SN号', max_length=128, unique=True)
asset_type_choices = (
('server', u'服务器'),
('switch', u'交换机'),
('router', u'路由器'),
('firewall', u'防火墙'),
('storage', u'存储设备'),
('NLB', u'NetScaler'),
('wireless', u'无线AP'),
('software', u'软件资产'),
('others', u'其它类'),
)
asset_type = models.CharField(u'资产类型',choices=asset_type_choices,max_length=64,blank=True,null=True)
manufactory = models.CharField(u'厂商', max_length=64,blank=True,null=True)
model = models.CharField(u'型号',max_length=128,blank=True,null=True)
ram_size = models.IntegerField(blank=True,null=True)
cpu_model = models.CharField(max_length=128,blank=True,null=True)
cpu_count = models.IntegerField(blank=True,null=True)
cpu_core_count = models.IntegerField(blank=True,null=True)
os_distribution = models.CharField(max_length=64,blank=True,null=True)
os_type = models.CharField(max_length=64,blank=True,null=True)
os_release = models.CharField(max_length=64,blank=True,null=True)
data = models.TextField(u'资产数据')
date = models.DateTimeField(u'汇报日期',auto_now_add=True)
approved = models.BooleanField(u'已批准',default=False)
approved_by = models.ForeignKey(UserProfile,verbose_name=u'批准人',blank=True,null=True)
approved_date = models.DateTimeField(u'批准日期',blank=True,null=True) class Meta:
verbose_name = '新上线待批准资产'
verbose_name_plural = "新上线待批准资产" def __str__(self):
return self.sn
数据表结构
自定义用户认证
https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#django.contrib.auth.models.PermissionsMixin.has_perms
浅谈Restful API
理解RESTful架构 :http://www.ruanyifeng.com/blog/2011/09/restful
RESTful API 设计指南:http://www.ruanyifeng.com/blog/2014/05/restful_api.html
python之CMDB的更多相关文章
- Python Django CMDB项目实战之-3创建form表单,并在前端页面上展示
基于之前的项目代码 Python Django CMDB项目实战之-1如何开启一个Django-并设置base页.index页.文章页面 Python Django CMDB项目实战之-2创建APP. ...
- Python Django CMDB项目实战之-2创建APP、建模(models.py)、数据库同步、高级URL、前端页面展示数据库中数据
基于之前的项目代码来编写 Python Django CMDB项目实战之-1如何开启一个Django-并设置base页index页文章页面 现在我们修改一个文章列表是从数据库中获取数据, 下面我们就需 ...
- Python Django CMDB项目实战之-1如何开启一个Django-并设置base页、index页、文章页面
1.环境 win10 python 2.7.14 django 1.8.2 需要用到的依赖包:MySQLdb(数据库的接口包).PIL/pillow(处理图片的包) 安装命令: pip install ...
- Python之CMDB资产管理系统
最近正好在给公司做CMDB资产管理系统,现在做的也差不多了,现在回头吧思路整理下. CMDB介绍 CMDB --Configuration Management Database 配置管理数据库, C ...
- python之路 目录
目录 python python_基础总结1 python由来 字符编码 注释 pyc文件 python变量 导入模块 获取用户输入 流程控制if while python 基础2 编码转换 pych ...
- Python开发环境-Pyenv安装使用
安装使用-Pyenv 简单的python版本管理:pyenv 管理python解释器 管理python版本 管理python的虚拟环境 官网:https://github.com/pyenv/pyen ...
- pyenv 配置python虚拟环境
安装pyenv环境 yum -y install git yum install gcc make patch gdbm-devel openssl-devel sqlite-devel readli ...
- 1-编程基础及Python环境部署
目录 1 编程基础 1.1 基本概念 1.2 语言分类 1.3 高级语言的发展 2 程序 3 python的语言介绍 4 Python的解释器 5 Python版本区别 6 Python安装 6.1 ...
- 1. Python 基础概述 和 环境安装
目录 Python 推荐书籍 开发环境 - Pyenv pyenv 使用 设置Python版本 virtualenv 虚拟环境 pip 通用配置 pip导出和导入 Jupyter 安装和配置 安装 j ...
随机推荐
- Tornado教程目录
第一章:引言 第二章:表单和模板 第三章:模板扩展 第四章:数据库 第五章:异步Web服务 第六章:编写安全应用 第七章:外部服务认证 第八章:部署Tornado
- Java - PriorityQueue
JDK 10.0.2 前段时间在网上刷题,碰到一个求中位数的题,看到有网友使用PriorityQueue来实现,感觉其解题思想挺不错的.加上我之前也没使用过PriorityQueue,所以我也试着去读 ...
- iOS开发网络篇—Socket编程
一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程 ...
- Java回顾之JDBC
这篇文章里,我们来讨论一些和JDBC相关的话题. 概述 尽管在实际开发过程中,我们一般使用ORM框架来代替传统的JDBC,例如Hibernate或者iBatis,但JDBC是Java用来实现数据访问的 ...
- 智课雅思词汇---二十七、形容词后缀-ant/-ent
智课雅思词汇---二十七.形容词后缀-ant/-ent 一.总结 一句话总结: ...的 后缀:-ant ①[形容词后缀] 大部分与-ance或-ancy,相对应,表示属于...的.具有...性质的 ...
- recv,recvfrom,send,sendto
一般情况下:send(),recv()用于TCP,sendto()及recvfrom()用于UDP 但是send(),recv()也可以用于UDP,sendto()及recvfrom()也可以用于TC ...
- linux-mint下搭建android,angularjs,rails,html5开发环境
目录[-] 必备软件: 环境配置: [open-jdk-6.0] [android-sdk] [ant] [github] [node.js] [rvm](ruby-1.9.3 rails-4.0.0 ...
- LeetCode 47
class Solution { public: vector<vector<int>> permuteUnique(vector<int>& nums) ...
- AutoFac IoC DI 依赖注入
AutoFac IoC DI 依赖注入 记录点点滴滴知识,为了更好的服务后来者! 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌 ...
- VS中的生成事件
1:为什么需要使用生成事件? 在实际开发过程中,一个公共使用的类库,在项目生成DLL后需要被复制到不同的目录下被引用,是不是觉得每次生成之后都需要人工复制是很麻烦的一件事情 我们可以利用VS中的项目生 ...