web-dev-qa-db-fra.com

Créer dynamiquement un objet de <Type>

J'ai une table dans ma base de données que j'utilise pour gérer les relations à travers mon application. c'est assez basique dans sa nature - parentType, parentId, childType, childId ... tous en tant qu'ints. J'ai déjà fait cette configuration, mais je l'ai fait avec une configuration de commutateur/boîtier lorsque j'avais 6 tables différentes que j'essayais de lier. Maintenant, j'ai 30 tables avec lesquelles j'essaie de le faire et j'aimerais pouvoir le faire sans avoir à écrire 30 entrées de cas dans ma commande switch.

Existe-t-il un moyen de faire référence à une classe .Net à l'aide d'une chaîne? Je sais que ce n'est pas valide (car j'ai essayé plusieurs variantes de cela):

Type t = Type.GetType("WebCore.Models.Page");
object page = new t();

Je sais comment obtenir le type d'un objet, mais comment l'utiliser à la volée pour créer un nouvel objet?

42
thaBadDawg

Ce lien devrait aider:

http://msdn.Microsoft.com/en-us/library/system.activator.createinstance (VS.71) .aspx

Activator.CreateInstance créera une instance du type spécifié.

vous pouvez envelopper cela dans une méthode générique comme celle-ci:

public T GetInstance<T>(string type)
{
    return (T)Activator.CreateInstance(Type.GetType(type));
}
57
Jason Miesionczek

Si le type est connu de l'appelant, il existe un moyen meilleur et plus rapide que d'utiliser Activator.CreateInstance: vous pouvez utiliser à la place une contrainte générique sur la méthode qui spécifie qu'il a un constructeur sans paramètre par défaut.

Le faire de cette façon est sûr pour le type et ne nécessite pas de réflexion.

T CreateType<T>() where T : new()
{
   return new T();
}
13
Judah Gabriel Himango
public static T GetInstance<T>(params object[] args)
{
     return (T)Activator.CreateInstance(typeof(T), args);
}

J'utiliserais Activator.CreateInstance () au lieu de lancer, car l'activateur a un constructeur pour les génériques.

10
AmuuuInjured

Vous souhaitez utiliser Activator.CreateInstance .

Voici un exemple de son fonctionnement:

using System;
using System.Runtime.Remoting;

class Program
{
    static void Main()
    {
        ObjectHandle o = Activator.CreateInstance("mscorlib.dll", "System.Int32");

        Int32 i = (Int32)o.Unwrap();
    }
}
9
Andrew Hare

Voici une fonction que j'ai écrite qui clone un enregistrement de type T, en utilisant la réflexion. Il s'agit d'une implémentation très simple, je n'ai pas géré de types complexes, etc.

 public static T Clone<T>(T original)
    {
        T newObject = (T)Activator.CreateInstance(original.GetType());

        foreach (var prop in original.GetType().GetProperties())
        {
            prop.SetValue(newObject, prop.GetValue(original));
        }

        return newObject;
    }

J'espère que cela peut aider quelqu'un.

Assaf

1
Assaf S.

En supposant que vous ayez le type suivant:

public class Counter<T>
{
  public T Value { get; set; }
}

et avoir le nom qualifié d'assembly du type, vous pouvez le construire de la manière suivante:

string typeName = typeof(Counter<>).AssemblyQualifiedName;
Type t = Type.GetType(typeName);

Counter<int> counter = 
  (Counter<int>)Activator.CreateInstance(
    t.MakeGenericType(typeof(int)));

counter.Value++;
Console.WriteLine(counter.Value);
0
sduplooy