Frage

Ich erstelle eine wiederverwendbare Bibliothek für Silverlight.Die Bibliothek enthält einen internen generischen Typ und ich muss eine neue Instanz dieses generischen Typs erstellen, aber ich habe zu einem bestimmten Zeitpunkt kein generisches Typargument verfügbar, sondern nur ein System.Type objekt, das das generische Argument darstellt.Ich habe versucht, eine Instanz mithilfe von Reflection zu erstellen, dies schlägt jedoch fehl, da diese Klasse intern ist und Silverlight effektiv teilweise vertrauenswürdig ausgeführt wird.

Folgendes habe ich bisher versucht:

private INonGenericInterface CreateInstance(Type type)
{
    // Activator.CreateInstance fails
    var instance = Activator.CreateInstance(
            typeof(InternalGenericType<>).MakeGenericType(type));

    // Invoking the default constructor of that type fails.
    var producer = typeof(InternalGenericType<>)
        .MakeGenericType(type)
        .GetConstructor(new Type[0])
        .Invoke(null);

    return (INonGenericInterface)producer;
}

Das ist mein innerer Typ.Nichts Besonderes:

internal class InternalGenericType<T> : INonGenericInterface
    where T : class
{
    public InternalGenericType()
    {
    }
}

Ich habe sogar versucht, das zu missbrauchen Nullable<T> struktur als Fabrik zum Erstellen einer Fabrik, die meinen internen Typ produzieren könnte.Standard jedoch Nullable<T> in Nullreferenzen konvertiert werden:

internal static class InternalGenericTypeFactory
{
   public static INonGenericInterface Create(Type serviceType)
   {
      var nullType = typeof(Nullable<>).MakeGenericType(
         typeof(Factory<>).MakeGenericType(serviceType));

      // Activator succesfully creates the instance, but .NET
      // automatically converts default Nullable<T>s to null.
      object nullInstance = Activator.CreateInstance(nullType);

      var getValueMethod =
         nullType.GetMethod("GetValueOrDefault", new Type[0]);

      // Invoke fails, because nullInstance is a null ref.
      var factory = getValueMethod.Invoke(nullInstance, null);

      return ((IFactory)factory).CreateInstance();
   }

   internal interface IFactory
   {
      INonGenericInterface CreateInstance();
   }

   internal struct Factory<T> : IFactory where T : class
   {
       public INonGenericInterface CreateInstance()
       {
           return new InternalGenericType<T>();
       }
   }
}

Wie Sie sich vorstellen können, möchte ich diesen Typ nicht veröffentlichen, da er meine API verschmutzen würde.Mir gehen momentan die Ideen aus.Was sind meine Optionen?Was kann ich tun, um diesen internen Typ zu erstellen?

War es hilfreich?

Lösung

Die dritte Alternative besteht darin, eine Art Factory-Muster zu unterstützen, das eine Methode zum Instanziieren des internen Typs enthält.Und Sie können die Fabrik freilegen oder den Fabriktyp öffentlich machen.

public class TypeFactory
{
    public static object Create<T>()
    {
         return new MyInternalType<T>();
    }
}

Sie können die Klasse als intern belassen und die Methode von TypeFactory über Reflektion aufrufen.

public object CreateType(System.Type type)
{
    Type typeFactory = typeof(TypeFactory);
    MethodInfo m = typeFactory.GetMethod("Create").MakeGenericMethod(type);
    return m.Invoke(null, null);
}

Ich denke, Ihre TypeFactory sollte öffentlich sein, sie kann nicht intern sein.

Andere Tipps

Sie haben zwei Möglichkeiten:

  1. Machen Sie den Typ öffentlich
  2. Vermeiden Sie dazu die Verwendung von Reflektion, sondern verwenden Sie stattdessen Generika.

Wenn die Sicherheitsvorkehrungen vermieden werden könnten, nur weil Sie sie nicht mögen, wäre es überhaupt nicht nötig, sie zu haben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top