Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   .NET-Sprachen (https://www.delphipraxis.net/82-net-sprachen/)
-   -   Zugriff auf Methode einer generischen Liste (https://www.delphipraxis.net/166484-zugriff-auf-methode-einer-generischen-liste.html)

Iwo Asnet 15. Feb 2012 09:52

Zugriff auf Methode einer generischen Liste
 
Hallo,

Ich habe eine Liste
Code:
class MyList<T> where T : MyObject
{
  public void Foobar()
}
Nun habe ich eine Methode mit folgender Signatur, der eine Instanz von MyList<?> übergeben wird:
Code:
void CallFooBar (object obj)
{
  // sowas will ich
  // ((MyList<???>)obj).FooBar;
}
Ich will also ein Objekt auf eine generische Liste casten, und dann eine bestimmte Methode dieser Listenklasse aufrufen. Es ist egal, von welchem Typ die Elemente sind ('T' ist also unerheblich).

Elvis 5. Mär 2012 21:30

AW: Zugriff auf Methode einer generischen Liste
 
Hiho,
Wenn du Kontrolle über die generische klasse hast, solltest du dort ein nicht-generisches Interface "implementieren" welches nur diese eine Methode kennt.

Code:
interface ISample
{
  void Fobar();


class MyList<T> : ISample
{
   void Foobar()
  {
      ...
  }
}
Code:
 var miep = 0 new MyList<int>();
object untypedRef = miep;
var mööp = untypedRef as ISample;
if(mööp != null)
  mööp.Foobar();
Wenn du keine Kontrolle über besagte Klasse hast, musst du Reflection nehmen:
Code:
var mi = untypedRef.GetType().GetMethod("Foobar", BindingFlags.Public | BindingFlags.Instance);
mi.DynamicInvoke(untypedRef, null);
Da das ständige Nachslagen Zeit dauert, ist es dann besser, den Call in einem Delegate pro Type abzulegen:
Code:
 static class Miep
{
  static readonly IDictionary<Type, Action<Object>> FoobarCallsByType = new Dictionary<Type, Action<Object>>();

  public static void InvokeFoobar(Object callee)
  {
    var typeRef = callee.GetType();
    lock(FoobarCallsByType)
    {
      Action<Object> foobar;
      if(!FoobarCallsByType.TryGetValue(typeRef, out foobar))
      {
        var mi = typeRef.GetMethod("Foobar", BindingFlags.Public | BindingFlags.Instance);
        FoobarCallsByType.Add(typeRef,
                              foobar = (Action<Object>)Delegate.CreateDelegate(typeof(Action<Object>), mi));
      }
    }
    foobar(callee);
  }
}
Das ist zwar viel langsamer als die erste Variante (ohne Reflection), aber besser als ständig Reflection anzuwerfen ist es auf jeden Fall, gerade wenn man es öfter aufruft...


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:35 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz