[MSCE C++]读取参数化cell参数的问题

 如图所示:我才用代码读取 某一个参数cell 的 属性(参数),发现可以读取 Genneral、Geometry、Raw Data、等板块的信息,但是 Variables 板块的信息 没有读取到, 请问大神 是什么原因?

具体代码如下:

bool doubleClickCallbackFunc2(DisplayPathCP path)
{
	WString filename;
	ElementRefP		eP = path->GetHeadElem();
	DgnModelRefP	currFileP = mdlDisplayPath_getPathRoot(path);
	MSElementDescrP elDescr;

	mdlElmdscr_getByElemRef(&elDescr, eP, currFileP, FALSE, NULL);
	EditElementHandle eeh(elDescr, FALSE, TRUE , 0);
	FindInstancesScopePtr scope = FindInstancesScope::CreateScope(eeh, FindInstancesScopeOption(DgnECHostType::All));
	 ECQueryPtr query = ECQuery::CreateQuery(ECQUERY_PROCESS_SearchAllClasses);
 DgnECInstanceIterable iterable = Bentley::DgnPlatform::DgnECManager::GetManager().FindInstances(*scope, *query);
 DgnECInstancePtr instance = *((iterable.begin()));

 ECN::ECClassCR instanceClass = instance->GetClass();
 ECPropertyIterable properties = instanceClass.GetProperties();

 for (ECPropertyIterable::const_iterator it0 = properties.begin(); it0 != properties.end(); ++it0)
 {
  ECValue v;
  ECPropertyCP pProp = (*it0);

  WString ddeea = pProp->GetTypeName();
  WString  ecpName = pProp->GetName();
  WString  ecpDesc = pProp->GetDescription();
  WString  ecpVVV = pProp->GetInvariantDescription();
  WString ersV = pProp->GetDisplayLabel();
  mdlDialog_dmsgsPrint(WPrintfString(L"名称:%s  类型:%s  内容:%s", ecpName, ddeea,  ersV));
 
 }
 filename.Sprintf(L"D:\\1.xml");
		instance->WriteToXmlFile(filename.data(), true, true);
		instance->WriteChanges();
mdlDialog_dmsgsPrint(WPrintfString(L"名称:%s 内容:%s ", L"长度:", L"123" ));

	return true;
}

Parents Reply
  •  老师好,我经过测试后 发现 外层指的是 我途中 1和2 两个 部分(也就是您说的“  iterable是一个集合  ”),但是 我只需要 1(project)的属性信息。 所以 我去掉了 那部分 循环。当然这个是我的理解 ,老师您看看是不是 我理解的有问题。

    另外,辛苦老师 帮我 看一下 如何获取  project  这个标签下的  variables 的 信息。  多谢老师的指正!!!

    Bentley 二次开发小白一枚

Children
  • 理解有误,一个元素上可以有多个ECInstance,FindInstances就是获取了元素上所有ECInstace的集合。您需要迭代这个集合,而您上边的代码只是访问了第一个ECInstance。

  •  老师 ,你看一下 ,我的元素 下面有一个 test1,test1下由两个 items,分别是 Project 和 test1, 那这两个 items  是不是就是您说的  ECInstance ?

    Bentley 二次开发小白一枚

  • 这个是您自定义的ECClass类型或者ItemType(基于EC)的属性,往元素添加一个ECInstance确实会在这里多出一项。但是不能理解为这就是ECInstance。Properties窗口里边看到的属性都是基于EC的,都是通过ECInstance附着到元素上的。EC机制比较复杂,是用一种往元素上添加自定义属性的公用格式,通过这种格式添加到元素上的属性,其他人即使没有你的程序也能读取到你通过EC添加到自定义属性。添加自定义属性时,首先你需要定义数据的类型ECClass,类似于你编程时,定义的struct或者class,结构体只是一种类型,往元素上添加时,你要用这个ECClass创建一个ECInstance。就好比你在编程时用到某个struct或者class,要实例化一个对象实例。之后把这个ECInstance附加到元素上即可。而ECSchema跟ECClass的关系类似于c++中命名空间跟struct或者class的关系。

  • 老师好!

      针对您的回复,还是不太明白,见谅!! 

    另外,上面您的方法 可以读取到 哪些属性信息吗?或者  怎么样才能可以读出来那些信息呢?

    请老师 指点!!!!!

    老师 我这里 还有一部分代码,可以完全替代上面我编写 的那段代码,可以检索到  我想要 检索的  变量名称  类型等 信息。

    但是 我 看不出来 他们的区别 ,您看一下 ,帮我解读一下 ,从业务逻辑 和 结构上 ,谢谢老师 !!!!

    具体代码如下:

    	ElementRefP		eP = path->GetHeadElem();
    	DgnModelRefP	currFileP = mdlDisplayPath_getPathRoot(path);
    	int itype=elementRef_getElemType(eP);
    	MSElementDescrP elDescr;
    
    	mdlElmdscr_getByElemRef(&elDescr, eP, currFileP, FALSE, NULL);
    	ParametricCellDefHandler& defHdler = ParametricCellDefHandler::GetInstance();
    	
    	BeFileName						activeCellLibraryName;
    	DgnFileP						pLibObj;
    	WChar							wCellName[MAX_CELLNAME_LENGTH];
    	DgnFileP						pDgnFile = ISessionMgr::GetActiveDgnFile();
    	int								iStatus;
    	DgnIndexIteratorP				pDgnIndexIterator;
    	DgnIndexItemP					pDgnIndexItem;
    	ElementRefP						ElDefRef=NULL;
    	DgnPlatform::DgnModelType 		ctype;
    	bool							is3D;
    
    	mdlCell_getLibraryName(activeCellLibraryName);//此处是读取激活的存放cell目录或.cel文件
    	iStatus = mdlCell_getLibraryObject(&pLibObj, activeCellLibraryName.c_str(), true);
    
    	pDgnIndexIterator = mdlModelIterator_create(pLibObj);
    	mdlModelIterator_setAcceptCellsOnly(pDgnIndexIterator, true);
    	/*下面是一个遍历模板库(cell文件)中模型的功能,要求改模板库只能有一个模型,也就是说找到一个模型后即可停止遍历
    	   ,并获取改模型的名称和其他信息。然后从该模型中获取cell的参数化信息。这里有一个非常重要的前提,就是需要明确
    	   一个模板库必须且只能有一个模型,每个模型中只能有一个cell的强烈要求和限制。通过这个规则来进行约束。
    	   因此目前这个遍历模板库中模型的算法,也就丧失了意义,因为根本不存在遍历的条件或基础。
    	*/
    	while (pDgnIndexItem = mdlModelIterator_getNext(pDgnIndexIterator) )
    	{
    		mdlModelItem_getName(pDgnIndexItem, wCellName, MAX_CELLNAME_LENGTH);		
    		mdlModelItem_getData(pDgnIndexItem, &ctype, &is3D, NULL, NULL, NULL);
    		ElDefRef = defHdler.FindByName((WCharCP)wCellName, *pDgnFile);
    		if (ElDefRef != nullptr)
    			break;
    	}
    	/*找到需要的模型后,查找该模型下参数化的单元,因为有前提条件和要求,所以可直接查找该模型下的参数化信息。*/
    	ParametricCellDefinitionPtr PaDef = defHdler.GetCellDefinition(ElementHandle(ElDefRef) );
    	//ParametricCellInfoPtr PaInfo = ParametricCellInfo::Create(status, *PaDef, setName, *pDgnModel);
    	IParameterDefinitionsPtr paramDefs = PaDef->GetParameterDefinitions();
    	VirtualCollectionIterator<IParameterDefinitionsIterator> iterEnd = paramDefs->end();
    	for (VirtualCollectionIterator<IParameterDefinitionsIterator> iter = paramDefs->begin(); iter != iterEnd; ++iter)
    	{
    		//ECValue val1;
    		//mdlDialog_dmsgsPrint( (*iter).GetDisplayLabel() );
    		WCharCP ddd = (*iter).GetDisplayLabel();//变量名称
    		WCharCP fff = (*iter).GetAccessString();//变量值
    		//ParameterType  rtt = (*iter).GetType();//变量类型
    		
    		mdlDialog_dmsgsPrint(WPrintfString(L"名称:%s 内容:%s ", ddd, fff ));
    	}

    Bentley 二次开发小白一枚

  • 前一种方法是自己写程序解析ECClass、ECProperty、ECInstance里边的内容,因为承载参数化单元参数值的ECClass结构非常复杂,解析起来非常麻烦,所以SDK又封装了一层接口,接口在后头已经完全处理好了调用起来相对简单多了。EC是基于XAttribute的,如果您没使用或者了解过XAttribute的话确实不好理解EC。通过XAttribute往元素上存储数据时,需要先定义一个c/c++的结构体,然后实例化一个对象实例,最后把这个实例挂到元素上边,这个属性会通过你自己程序中定义的一个ID值来区别于其他的XAttribute。读取的时候通过这个ID值来获取,想想一下如果只有这个ID值,而没有c/c++结构体的定义,获取XAttribute时返回了一个指针,程序中你怎么解析这个指针指向的内存区域呢?你完全解析不出来,所以为了方便业务数据在不同专业之间的交流,诞生了EC。通过EC存储属性的话,定义数据结构时不再是像XAttribute那样,声明一个c/c++的结构体,而是在一个xml中定义一个ECClass(可以参考C:\Program Files\Bentley\MicroStation CONNECT Edition\MicroStation\ECSchemas\Dgn这个路径下的xml文件),往元素上挂接ECInstance的时候,这个ECClass的内容也会保存到dgn文件中。这个时候其他人在读取你通过EC机制添加的属性时,后台会在dgn文件中找到对应的ECClass,随后当然也能解析出你添加的属性了。