2010-12-21 10 views
0

Ich versuche, eine Methodenfactory zu erstellen, die innerhalb der Konfiguration sucht, um den vollständigen Namen des Typs zu erhalten, der instanziiert wird, und diesen Objekttyp dynamisch erstellt.Fehler beim dynamischen Erstellen des Typs

Hier mein Typ ist und die Schnittstelle:

public interface IComponent<T> 
{ 
    IEnumerable<T> DataSource {get; set;} 

    void PerformTask(object executionContext); 

} 

namespace MyCompany.Components 
{ 
    public class ConcreteComponent1<T> : IComponent<T> 
    { 

     private IEnumerable<Contact> contactSource = null; 

     internal ConcreteComponent1() {} 

     public void PerformTask(object executionContext) 
     { 
      this.contactSource = GetSource(executionContext); 

      foreach(var result in this.contactSource) 
      { 
       result.Execute(executionContext); 
      } 
     } 

     public IEnumerable<T> DataSource 
     { 
      get { return this.contactSource as IEnumerable<T>; } 
      set { this.contactSource = (IContactSource)value; } 
     } 
    } 
} 

Fabrik, befindet sich in der gleichen Baugruppe:

//Factory - Same assembly 
public static class ComponentFactory<T> 
{ 
    public static IComponent<T> CreateComponent() 
    { 
     var assembly = Assembly.GetExecutingAssembly(); 
     object o = assembly.CreateInstance("MyCompany.Components.ConcreteComponent1"); //o is null... 

     var objectHandle = Activator.CreateInstance(Assembly.GetAssembl(typeof(ComponentFactory<T>)).GetName().FullName, "MyCompany.Components.ConcreteComponent1"); //throws Could not load type from assembly exception.      
     return o as IComponent<T>; 
    } 
} 

So in erster Fall der o immer null ist.

Im zweiten Fall, wenn die Activator-Klasse verwendet wird, kann der Typ Type nicht aus der Assembly "MyAssembly" geladen werden. Keine innere Ausnahme. Was mache ich falsch?

Antwort

1

Zunächst einmal tatsächlichen Namen Ihrer Art ist:

MyCompany.Components.ConcreteComponent1`1 

Es kann nicht instanziert werden, da Sie Typparameter angeben:

public static class ComponentFactory<T> 
{ 
    public static IComponent<T> CreateComponent() 
    { 
     Type generic = Type.GetType("MyCompany.Components.ConcreteComponent1`1"); 
     Type concrete = generic.MakeGenericType(typeof(T)); 
     var objectHandle = Activator.CreateInstance(
      concrete, 
      BindingFlags.NonPublic | BindingFlags.Instance, 
      null, 
      null, //here can come ctor params 
      null); 
     return objectHandle as IComponent<T>; 
    } 
} 

dies mit internal Konstruktor arbeiten.

+0

toll - danke für den Tipp. Eine Sache jedoch - den Bauunternehmer öffentlich zu machen, wird hier den ganzen Zweck der Fabrik besiegen. – dexter

+0

@Max Malygin überprüfen Sie die Bearbeitung, müssen Sie einige weitere Parameter hinzufügen, um 'interne' ctor – Andrey

+0

Ok, dachte, es muss ein Weg sein. – dexter

1

Ich würde sagen, der tatsächliche Name Ihrer Klasse ConcreteComponent1 ist nicht "MyCompany.Components.ConcreteComponent1", weil es eine generische enthält. Führen Sie

Console.WriteLine(typeof(ConcreteComponent1<T>).FullName); 

aus, um die von C# erstellte Zeichenfolgendarstellung für Ihre Klasse anzuzeigen.

Aber warum definieren Sie Ihre ConcreteComponent1-Klasse so wie Sie? Wäre es nicht besser sein, so etwas zu verwenden:

public class ConcreteComponent1 : IComponent<Contact> { 

     internal ConcreteComponent1() {} 

     public void PerformTask(object executionContext) 
     { 
       this.contactSource = GetSource(executionContext); 

       foreach(var result in this.contactSource) 
       { 
        result.Execute(executionContext); 
       } 
     } 

     public IEnumerable<Contact> DataSource 
     { 
       get { return this.contactSource; } 
       set { this.contactSource = value; } 
     } 
    } 

diese Weise können Sie den erwarteten Namen verwendet, um Sie bereits in Ihrem Beispiel verwenden können, und Sie können den zusätzlichen privaten Bereich Ihr Ansatz führt zu entfernen. Da Ihre ConcreteComponent1-Klasse keine generischen Funktionen benötigt, wäre dies meines Erachtens ein besserer Ansatz.

Verwandte Themen