2010-12-21 101 views
0

我试图想出一个方法工厂,它看起来内部配置获取类型的全名来实例化并动态创建该对象类型。无法动态创建类型

这里是我的类型和接口:

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; } 
     } 
    } 
} 

厂,位于同一组件:

//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>; 
    } 
} 

所以在第一种情况下Ø总是空。

在使用Activator类的第二种情况下,它会抛出Type无法从程序集“MyAssembly”中加载。没有内在的例外。我究竟做错了什么?

回答

1

首先,你的类型的实际名称是:

MyCompany.Components.ConcreteComponent1`1 

它不能被实例化,因为你必须指定类型参数:

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>; 
    } 
} 

这将internal构造工作。

+0

很好 - 谢谢你的提示。有一件事 - 公开构造函数将会击败工厂的全部目的。 – dexter 2010-12-21 18:16:22

1

我会说你的类ConcreteComponent1的实际名称不是“MyCompany.Components.ConcreteComponent1”,因为它包含一个泛型。执行

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

查看C#创建的类的字符串表示。

但是你为什么要定义你的ConcreteComponent1类?那岂不是更好地使用这样的事情:

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; } 
     } 
    } 

这样,您就可以使用您已经在示例中使用的预期的名称,你可以删除你的方法引入了额外的私人领域。由于您的ConcreteComponent1类实际上并不需要任何通用功能,因此在我看来这是更好的方法。