在我的应用程序中,我使用mpxj从microsoft项目文件中提取项目 - 我需要的项目之一是前辈。我能够拉出前辈的方法是使用mpxj的build函数返回一种类型的java.util.list - 我可以将它保存为变量作为对象,但我需要找到一种方法将数据带到我可以轻松使用的格式,因此我可以将其存储到数据库中。下面列出了我用来从项目文件中提取前驱的代码行。
Dim predecessors = task.getPredecessors
以下是将tracepoint放入以获取前驱的值
的结果[[Relation [Task id=4 uniqueID=45577 name=Standards Training - Round 2] -> [Task id=3 uniqueID=45576 name=Process Excellence Training]]]
即使我可以将上面的字符串作为字符串,我也可以使用它来获取我需要的数据。上面的示例是前置列表中有1个项目,但有时会有多个项目。以下是有多个项目时的跟踪点示例。
[[Relation [Task id=63 uniqueID=45873 name=Complete IP Binder] -> [Task id=47 uniqueID=45857 name=Organizational Assessment]], [Relation [Task id=63 uniqueID=45873 name=Complete IP Binder] -> [Task id=49 uniqueID=45859 name=Document Deliverables]], [Relation [Task id=63 uniqueID=45873 name=Complete IP Binder] -> [Task id=56 uniqueID=45866 name=Infrastructure Deliverables]], [Relation [Task id=63 uniqueID=45873 name=Complete IP Binder] -> [Task id=58 uniqueID=45868 name=IT Deliverables]], [Relation [Task id=63 uniqueID=45873 name=Complete IP Binder] -> [Task id=60 uniqueID=45870 name=Organizational Deliverables]]]
感谢您的帮助。
答案 0 :(得分:4)
在C#3.5+中,由于yield
关键字,创建一个扩展方法为这些Java列表提供一个好的,类型安全的枚举器非常简单。你可以这样做:
public static class JavaExtensions
{
public static IEnumerable<T> toIEnumerable<T>(this java.util.List list)
{
if (list != null)
{
java.util.Iterator itr = list.iterator();
while (itr.hasNext())
{
yield return (T)itr.next();
}
}
}
}
只要包含此扩展名的命名空间对您的代码可见,那么您只需执行以下操作即可与前任一起使用:
foreach (var relation in task.getPredecessors().toIEnumerable<Relation>())
{
Task sourceTask = relation.getSourceTask();
//etc.
}
不幸的是,你使用的是VB.Net。我和你在同一条船上,最后创建了一个单独的C#类库,我在VB ASP.NET项目中引用它。这样我就可以在处理IKVM Java风格的对象时获得C#语法的好处,而无需转换我的整个项目。
如果您不想这样做,可以使用an online code converter将Jon的代码(不使用任何C#-only功能)更改为VB并将其包含在项目中。
上面的主要内容是,您不需要使用在调试器中看到的字符串表示(只是在该列表中的Relation对象上调用toString())。 getPredecessors()
函数返回Relation
个对象的列表。
Dim predecessorList as java.util.List = task.getPredecessors()
Dim iter as java.util.Iterator = predecessorList.iterator()
Do While iter.hasNext()
Dim curRelation as Relation = iter.next()
'gets the left side of the relationship (the task you are dealing with)
Dim sourceTask as Task = curRelation.getSourceTask()
'gets the task that is the predecessor to the 'source' task
Dim targetTask as Task = curRelation.getTargetTask()
'from here you can call methods on the Task objects to get their other properties
'like name and id
Loop
答案 1 :(得分:1)
使用IKVM生成的.Net程序集时,有两种方法可以使用Java集合。第一种是用Java方式做事并使用迭代器:
java.util.List predecessors = task.getPredecessors();
java.util.Iterator iter = predecessors.iterator();
while (iter.hasNext())
{
Relation rel = (Relation)iter.next();
System.Console.WriteLine(rel);
}
另一种方法是添加一些“可用性”代码来隐藏它:
foreach(Relation rel in ToEnumerable(task.getPredecessors()))
{
System.Console.WriteLine(rel);
}
为此,我创建了“ToEnumerable”方法:
private static EnumerableCollection ToEnumerable(Collection javaCollection)
{
return new EnumerableCollection(javaCollection);
}
和EnumerableCollection类,它隐藏了迭代器的使用:
class EnumerableCollection
{
public EnumerableCollection(Collection collection)
{
m_collection = collection;
}
public IEnumerator GetEnumerator()
{
return new Enumerator(m_collection);
}
private Collection m_collection;
}
public struct Enumerator : IEnumerator
{
public Enumerator(Collection collection)
{
m_collection = collection;
m_iterator = m_collection.iterator();
}
public object Current
{
get
{
return m_iterator.next();
}
}
public bool MoveNext()
{
return m_iterator.hasNext();
}
public void Reset()
{
m_iterator = m_collection.iterator();
}
private Collection m_collection;
private Iterator m_iterator;
}
更有趣的方法是使用Extension Methods将此功能添加到java Collection类中,这将使您的代码不那么混乱。我计划在下一个版本中尝试将包含有用扩展方法的程序集作为MPXJ的一部分发布。
答案 2 :(得分:0)
能够通过使用tostring来完成这个,然后左右切出我需要的东西,更快 - 不知道为什么这个被删除之前