2010-12-06 8 views
0

Je pense qu'il est plus difficile de demander que de répondre à la question. Je veux poser ma question avec un exemple: Vous savez que nous pouvons lier un objet à un DataSource, et cet objet pourrait être de n'importe quel type. Alors supposons que j'ai lié un objet de type "MyClass" à DataSource d'un DataSet. Maintenant, j'envoie ce jeu de données en tant que paramètre à une autre classe dans une autre DLL, et dans ce fichier DLL, je veux créer une liste <> de type "MyClass". Comme je l'ai pas accès à type « MyClass » Je peux utiliser ce code pour obtenir le type de DataSource:C# - Comment passer un type en paramètre

_dataSet.DataSource.GetType() 

mais je ne peux pas utiliser le code comme suit pour créer une liste de type de « MyClass ": List<_dataSet.DataSource.GetType()> _list;

Que dois-je faire dans cette situation?

+2

Quel serait le point à faire cela bien? La seule raison pour laquelle vous voulez la liste générique est que vous pouvez utiliser le type spécifique, puisque vous ne connaissez pas le type que vous ne pouvez pas utiliser de toute façon, pourrait aussi bien utiliser un simple tableau d'objets. – Doggett

+1

La réflexion et les génériques ne sont généralement pas de bons compagnons de lit ... cela peut se faire, bien sûr, mais ça vous combat à chaque pas ... Je considérerais un design plus simple (et oui, il y en a plusieurs) –

Répondre

1

Il y a essentiellement deux options:

  1. bâton avec List<object> ou, mieux, nous le type le plus proche ancêtre connu de _dataSet.DataSource
  2. ou utilisez une réflexion désagréable hack pour instancier un List<T> dynamiquement.

Je personnellement recourir à l'option (1) dans la plupart des cas, car il est:

  • plus facile à utiliser,
  • lisible,
  • tapez suffisamment en sécurité,
  • universel termes de réutilisation du code naturel.

La deuxième option a déjà été élaborée dans d'autres réponses.

0
var newtype = typeof (List<>).MakeGenericType(_dataSet.DataSource.GetType()); 
var _list = Activator.CreateInstance(newtype); 
0

Vous pouvez créer dynamiquement un type générique utilisant la réflexion:

var listType = typeof(List<>).MakeGenericType(
    new[] { _dataSet.DataSource.GetType() } 
); 
var ctor = listType.GetConstructor(new Type[] { }); 
var list = ctor.Invoke(null); 

Notez que list sera typée comme object.

+1

le type est légèrement plus bas en utilisant IList, mais c'est aussi spécifique que vous obtiendrez. – LukeH

0

Vous devrez utiliser la réflexion pour instancier une liste générique du type souhaité. Cette méthode devrait faire l'affaire:

public object InstantiateGenericList(Type nodeType) 
{ 
    Type list  = typeof(List<>) ; 
    Type genericList = list.MakeGenericType(nodeType) ; 
    object instance = Activator.CreateInstance(genericList) ; 

    return instance ; 
} 
0

Vous pouvez utiliser la réflexion, que d'autres réponses ont souligné.

Avez-vous le contrôle sur l'autre classe dans l'autre DLL? Pouvez-vous rendre cette classe ou la méthode particulière que vous appelez sur cette classe générique?

public class SomeOtherClassInSomeOtherDLL 
{ 
    public void DoSomethingWithData<T>(T dataSource) 
    { 
     // ... 

     List<T> list = new List<T>(); 
     list.Add(dataSource); 

     // ... 
    } 
} 

Donc, vous l'appelez comme ceci:

 var anotherClass = new SomeOtherClassInSomeOtherDLL(); 

     // ... 

     anotherClass.DoSomethingWithData(_dataSet.DataSource as MyClass); 
Questions connexes