AE对象的深度克隆和不同数据集的值域拷贝
在AE二次开发过程中很多时候需要克隆对象,如IMap ,ILayer,IDomain,IElement等等,如果简单的用等于是行不通的,如果每一个细节的赋值,又容易遗漏很多东西。所以就提供了深度克隆的方法:
以IDomain深度克隆为例:
IObjectCopy pObjectCopy = new ObjectCopyClass();
object preDomain = pObjectCopy.Copy(perDomain);//对象的深度复制
IDomain acessDomain = preDomain as IDomain;
这样就会把值域的名称、描述及代码等细节都会一个不落的克隆过去。
#region 导出数据到本地数据库 /// <summary> /// 导出数据到本地数据库 /// </summary> /// <param name="exportDataName"></param> /// <param name="fatherDatasetName"></param> /// <param name="saveName"></param> /// <returns></returns> public bool ExportDataToLocalMDb(string exportDataName, string fatherDatasetName, string saveMdbFileName) { IDataset outDataset = GetDataset(exportDataName, fatherDatasetName); if (outDataset == null) { string msg = string.Format("{0} 中不包含 {1} 的相关数据!", fatherDatasetName, exportDataName); MessageBox.Show(msg, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return true; } IFeatureClass infeatCls = outDataset as IFeatureClass; IWorkspaceFactory pWSF = new ESRI.ArcGIS.DataSourcesGDB.AccessWorkspaceFactoryClass(); string mdbDirectoryStr = System.IO.Path.GetDirectoryName(saveMdbFileName); string mdbFileNameStr = System.IO.Path.GetFileNameWithoutExtension(saveMdbFileName); if (File.Exists(saveMdbFileName)) { MessageBox.Show("文件\"" + saveMdbFileName + "\"已存在,请重新选择数据库文件", "文件已存在", MessageBoxButtons.OK, MessageBoxIcon.Information); return false; } pWSF.Create(mdbDirectoryStr, mdbFileNameStr, null, 0); IWorkspace pWorkspace = pWSF.OpenFromFile(saveMdbFileName, 0); string outFeatClsName = outDataset.Name.Substring(outDataset.Name.IndexOf('.') + 1); SaveFeatureClassToAccessMdb(infeatCls, null, pWorkspace, outFeatClsName); IFeatureClass operaFeatCls = pWorkspace.OpenFeatureClass(outFeatClsName); //值域复制 if (pWorkspace != null) { CopyIDomainSDEToMDB(currentWorkspace, pWorkspace); } //有值域字段复制 if (operaFeatCls != null) { CopyDomainWithField(infeatCls, operaFeatCls); } return true; } /// <summary> /// 把值域从远程数据库复制到本地数据库中 /// </summary> /// <param name="sdeWSP">远程SDE数据库</param> /// <param name="accessWSP">本地MDB数据库</param> private void CopyIDomainSDEToMDB(IWorkspace sdeWSP, IWorkspace accessWSP) { IWorkspaceDomains sdeWSPDoms = (IWorkspaceDomains)sdeWSP ; IWorkspaceDomains accessWSPDoms = (IWorkspaceDomains)accessWSP; IEnumDomain sdeEnumDomain = sdeWSPDoms.Domains; //复制过程 if (sdeEnumDomain != null) { IDomain perDomain = null; while ((perDomain = sdeEnumDomain.Next()) != null) { //深度克隆 IObjectCopy pObjectCopy = new ObjectCopyClass(); object preDomain = pObjectCopy.Copy(perDomain);//对象的深度复制 IDomain acessDomain = preDomain as IDomain; if (CheckDomainExist(acessDomain.Name, accessWSPDoms) > -1) { accessWSPDoms.DeleteDomain(acessDomain.Name); } accessWSPDoms.AddDomain(acessDomain); } } } /// <summary> /// 检查域名是否存在 /// </summary> /// <param name="checkDomainName">值域名称</param> /// <param name="pWorkspaceDomains">域名</param> /// <returns></returns>若存在返回其域索引位置,不存在则返回-1 private int CheckDomainExist(string checkDomainName, IWorkspaceDomains pWorkspaceDomains) { IDomain domain = null; IEnumDomain enumDomain = pWorkspaceDomains.Domains; if (enumDomain != null) { while ((domain = enumDomain.Next()) != null) { if (domain.Name == checkDomainName) return domain.DomainID; } } return -1; } /// <summary> /// 输出过程中输出值域代码 /// </summary> /// <param name="sdeFClass">SDE数据库数据集</param> /// <param name="accessFClass">本地数据库数据集</param> private void CopyDomainWithField(IFeatureClass sdeFClass,IFeatureClass accessFClass) { int fieldCount = sdeFClass.Fields.FieldCount; //两个数据集的值域复制 IDataset pDset = accessFClass as IDataset; IWorkspaceDomains workapceDom = pDset.Workspace as IWorkspaceDomains; ISchemaLock schemaLock = (ISchemaLock)accessFClass; IClassSchemaEdit classSchemaEdit = (IClassSchemaEdit)accessFClass; for (int i=0;i<fieldCount;i++) { IField field = sdeFClass.Fields.get_Field(i); IFieldEdit pFieldEdit=field as IFieldEdit; if(pFieldEdit.Domain==null) continue; //深度克隆 IDomain acessDomain = workapceDom.get_DomainByName(pFieldEdit.Domain.Name); schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); classSchemaEdit.AlterDomain(field.Name, acessDomain); } } #endregion