简体   繁体   中英

How to use a specific interface on a C# object in IronPython

I have a C# class that implements 2 IEnumerable interfaces. How can I access either interface from IronPython?

My class:

public class MyClass : IEnumerable<TypeA>, IEnumerable<TypeB>
{
    IEnumerator<TypeA> IEnumerable<TypeA>.GetEnumerator()
    {
        return _lstTypeA.GetEnumerator();
    }

    IEnumerator<TypeB> IEnumerable<TypeB>.GetEnumerator()
    {
        return _lstTypeB.GetEnumerator();
    }
}

I tried the following in Python, but although it runs without errors it does not return any elements from the IEnumerable interface:

x = MyClass()
xA = clr.Convert(x, IEnumerable[TypeA])
for y in xA: print y

I don't like your class design. In particular that you implement two different versions of IEnumerable<T> that return different members. Two versions that return the same members is slightly better, but I still don't like that much.

  1. Implementing IEnumerable so it's consistent with both IEnumerable<T> s isn't possible here. In particular that breaks the OfType and Cast linq methods.
  2. You get overload resolution problems almost everywhere. Methods like Select<T>(this IEnumerable<T> ...) don't know which IEnumerable to take.
  3. You can't use foreach on MyClass
  4. If both TypeA and TypeB are reference types the variance of IEnumerable<out T> comes back to bite you. Since both of them offer IEnumerable<T'> for all their common ancestors.
  5. It doesn't interact well with dynamically types languages
  6. A class being a two different collections at the same time rarely makes sense. It usually indicates that something went wrong in the mapping from concepts to classes.
  7. It's confusing and hard to understand. My intuition tells me it's evil and that I should burn it with fire :P

And Probably several more issues I didn't think of yet.


The work around is simple and clean: Have two separate enumerable properties.

public class MyClass
{
  public IEnumerable<TypeA> TypeAs{get{_lstTypeA.Select(x=>x)}};
  public IEnumerable<TypeB> TypeBs{get{_lstTypeB.Select(x=>x)}};
}

You need to call methods and properties as you were using reflection (that is actually what it happens under the hood).

In your case you should do:

x = MyClass()
enumerator = IEnumerable[TypeA].GetEnumerator(x)

then you can loop over enumerator :

for y in enumerator:
   print y

how i use specified interface

clr.AddReference('Platform.CardHost')
from Platform import CardHost
from Platform.CardHost import ICardHost

host = CardHost.CardHost.CreateInstance('session')
# ICardHost is interface
# inside C# 
# public interface ICardHost {
# IExtensionManager ExtensionManager { get; }
em = ICardHost.ExtensionManager.__get__(host) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM