我有一个返回大量对象的C#方法。这将在Matlab中使用。
namespace MyNameSpace{
public static class MyClass{
public static IEnumerable<MyDataObject> GetVeryLargeResponse(){
while(CheckForSomeFunkyConditionThatsRarelyTrue()){
yield return GetMyNextDataObject();
}
yield break;
}
}
}
当我打电话时在Matlab中
result = MyClass.GetVeryLargeResponse();
我希望结果属于IEnumerable<MyDataObject>
类型,以便能够通过调用Enumerator<MyDataObject>
来获取result.GetEnumerator()
。
我在哪里result
MyNameSpace.<GetVeryLargeResponse>d_3
类型GetEnumerator()
没有result
方法可用。我确实看到System.Collections.Generic.IEnumerable<MyClass>
的超级班级之一是result
。
有没有办法可以在Matlab中迭代这个,甚至可以在Matlab中“IEnumerable<MyClass>
到Array
”。
P.S。
IList
/ IQueryable
等是不可行的
答案 0 :(得分:5)
结果 具有GetEnumerator()
方法 - 它可以通过显式接口实现来实现。
如果Matlab不愿意处理它,你总是可以编写自己的映射类型和扩展方法来简化:
public static class Extensions
{
public static EnumerableWrapper<T> Wrap<T>(this IEnumerable<T> source)
{
return new EnumerableWrapper<T>(source);
}
}
public class EnumerableWrapper<T> : IEnumerable<T>
{
private readonly IEnumerable<T> source;
public EnumerableWrapper(IEnumerable<T> source)
{
this.source = source;
}
public IEnumerator<T> GetEnumerator()
{
return new EnumeratorWrapper<T>(source.GetEnumerator());
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class EnumeratorWrapper<T> : IEnumerator<T>
{
private readonly IEnumerator<T> source;
public EnumeratorWrapper(IEnumerator<T> source)
{
this.source = source;
}
public T Current { get { return source.Current; } }
object IEnumerator.Current { get { return Current; } }
public bool MoveNext()
{
return source.MoveNext();
}
public void Reset()
{
source.Reset();
}
public void Dispose()
{
source.Dispose();
}
}
然后尝试:
result = MyClass.GetVeryLargeResponse().Wrap();
对于Matlab来说似乎很奇怪,但是开箱即用并不支持这个......
答案 1 :(得分:5)
考虑以下示例:
namespace MyNameSpace {
public class Person {
public string name { get; set; }
public int age { get; set; }
}
public class MyClass {
private static List<Person> people = new List<Person> {
new Person {name = "name1", age=10},
new Person {name = "name2", age=20},
new Person {name = "name3", age=30},
new Person {name = "name4", age=40},
new Person {name = "name5", age=50}
};
public static IEnumerable<Person> GetPeople() {
foreach (var p in people) {
yield return p;
}
}
}
}
%# load my assembly
str = 'C:\path\to\MyNameSpace.dll';
NET.addAssembly(str);
obj = MyNameSpace.MyClass.GetPeople(); %# IEnumerable<Person>
%# call ToArray() extension method: this forces immediate query evaluation
NET.addAssembly('System.Core'); %# contains 'System.Linq' namespace
arr = NET.invokeGenericMethod('System.Linq.Enumerable', 'ToArray', ...
{'MyNameSpace.Person'}, obj);
%# loop through results
for i=1:arr.Length
fprintf('name=%s, age=%d\n', char(arr(i).name), int32(arr(i).age));
end
代码产生输出:
name=name1, age=10
name=name2, age=20
name=name3, age=30
name=name4, age=40
name=name5, age=50
正如您所看到的,我确实将返回的对象转换为数组Person[]
(我意识到您试图避免)。奇怪的是,如果我们看一下类的层次结构:
>> superclasses(obj)
Superclasses for class MyNameSpace.<GetPeople>d__0:
System.Object
System.Collections.Generic.IEnumerable<MyNameSpace*Person>
System.Collections.IEnumerable
System.Collections.Generic.IEnumerator<MyNameSpace*Person>
System.IDisposable
System.Collections.IEnumerator
handle
你可以看到System.Collections.Generic.IEnumerator<Person>
,但不知何故该对象似乎没有暴露继承的GetEnumerator
方法:
>> methods(obj,'-full')
Methods for class MyNameSpace.<GetPeople>d__0:
MyNameSpace.<GetPeople>d__0 obj <GetPeople>d__0(int32 scalar <>1__state)
logical scalar RetVal Equals(MyNameSpace.<GetPeople>d__0 this, System.Object obj)
int32 scalar RetVal GetHashCode(MyNameSpace.<GetPeople>d__0 this)
System.Type RetVal GetType(MyNameSpace.<GetPeople>d__0 this)
System.String RetVal ToString(MyNameSpace.<GetPeople>d__0 this)
event.listener L addlistener(handle sources, char vector eventname, function_handle scalar callback) % Inherited from handle
event.proplistener L addlistener(handle sources, meta.property properties, char vector eventname, function_handle scalar callback) % Inherited from handle
event.proplistener L addlistener(handle sources, string propertyname, char vector eventname, function_handle scalar callback) % Inherited from handle
event.proplistener L addlistener(handle sources, cell propertynames, char vector eventname, function_handle scalar callback) % Inherited from handle
delete(handle obj) % Inherited from handle
logical TF eq(A, B) % Inherited from handle
handle HM findobj(handle H, varargin) % Inherited from handle
meta.property prop findprop(handle scalar object, string propname) % Inherited from handle
logical TF ge(A, B) % Inherited from handle
logical TF gt(A, B) % Inherited from handle
logical validity isvalid(handle obj) % Inherited from handle
logical TF le(A, B) % Inherited from handle
logical TF lt(A, B) % Inherited from handle
logical TF ne(A, B) % Inherited from handle
notify(handle sources, string eventname) % Inherited from handle
notify(handle sources, string eventname, event.EventData scalar eventdata) % Inherited from handle
答案 2 :(得分:0)
您需要使用显式强制转换。首先显式地转换IEnumerable实例:
result = MyClass.GetVeryLargeResponse();
resultEnumerable = NET.explicitCast(result,'System.Collections.IEnumerable');
然后得到枚举器:
resultEnumerator = resultEnumerable.GetEnumerator();
然后显式地转换枚举器:
resultEnumerator = NET.explicitCast(resultEnumerator, 'System.Collections.IEnumerator');
然后您可以根据需要迭代集合:
while (resultEnumerator.MoveNext)
resultEnumerator.Current
end