2 Stimmen

Wie ruft man eine Generika mit Einschränkungen auf, wenn der Typ nur zur Laufzeit bekannt ist?

Ich möchte eine Klasse, die Population von Listen von Daten aus einem Dropdown, die jeden Typ nehmen kann, wie ich lieber den externen Code aussehen haben würde behandelt:

listProvider.For<AnEnumType>().And<AClass>.GetLists();

als

listProvider.ForEnum<AnEnumType>().ForClass<AClass>.GetLists();

Hier ist der Beispielcode

public class Foo
{
    public void DoSomething<T>
    {
        if(typeof(T).IsEnum)
        {
           //Do Something
        } else if (typeof(T).IsClass)
        {
           var bar = new Bar();

           //Problem How to call bar as type T must be a reference type?
           bar.GetData<T>()
        }     
    }
}

public class Bar
{
    public IProvideList<T> GetData() where T : class
    {
        //Do Something
    }
}

public interface IProvideList<T> T : class
{

}

Zur Kompilierzeit weiß der Compiler nicht, dass T eine Klasse ist, aber ich weiß, dass er es zur Laufzeit weiß. Ich kann dies mit Reflection aufrufen:

bar.GetType().GetMethod("GetData").MakeGenericMethod(typeof(T));

Allerdings kann ich das Ergebnis beim Aufrufen der Methode nicht auf (IProvideList) zurückführen, da T ein Referenztyp sein muss.

Gibt es eine Möglichkeit, dies zu umgehen?

1voto

Alexey Raga Punkte 7335

Anstatt nur Bar können Sie Bar<T> und es fällt alles ganz natürlich zu:

public void DoSomething<T>
{
    if(typeof(T).IsEnum)
    {
       //Do Something
    } 
    else if (typeof(T).IsClass)
    {
       //Here you know T
       var bar = new Bar<T>();
       bar.GetData()
    }     
}

....
public class Bar<T>
{
    public IProvideList<T> GetData<T>() where T : class
    {
        //Do Something
    }
}

1voto

Özgür Kara Punkte 1334

Müssen Sie die where T : class in der Bar? Wenn nicht, versuchen Sie dies.

public class Foo
{
    public void DoSomething<T>()
    {
        if(typeof(T).IsEnum)
        {
           //Do Something
        } else if (typeof(T).IsClass)
        {
           var bar = new Bar();

           //Problem How to call bar as type T must be a reference type?
            bar.GetData<T>();
        }     
    }
}

public class Bar
{
    public IProvideList<T> GetData<T>() //where T : class
    {
        //Do Something
    }
}

public interface IProvideList<T> //where T : class
{

}

0voto

Gunner Punkte 867

Schließlich gelang es mir, dieses Problem zu umgehen, indem ich eine Reflexion durchführte:

bar.GetType().GetMethod("GetData").MakeGenericMethod(typeof(T));

Dann nicht versuchen, das Ergebnis zu casten, sondern Zugriff auf alle Methoden und Funktionen, die ich für das Ergebnis über Reflexion zu so:

var listProviderType = typeof (IProvideList<>).MakeGenericType(typeof (T));                    
var result = istProviderImplType.GetMethod("MethodINeedToCall").Invoke(listProviderImpl, null);   

Nicht gerade der schönste Code, den ich kenne, aber er führt zu dem gewünschten Ergebnis.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X