无法动态创建类型

发布于 2024-10-09 02:17:13 字数 1695 浏览 3 评论 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>;
    }
}

因此在第一种情况下 o 始终为 null。

在第二种情况下,当使用 Activator 类时,它会抛出无法从程序集“MyAssembly”加载类型。内心无异常。我做错了什么?

I am trying to come up with a method factory that looks inside config to get the full name of the type to instantiate and creates that object type dynamically.

Here is my Type and the Interface:

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, resides in the same assembly:

//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 first case the o is always null.

In the second case when using the Activator class, it throws Type could not be loaded from assembly "MyAssembly". No inner exception. What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

影子的影子 2024-10-16 02:17:32

我想说你的类 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 类实际上并不需要任何通用功能,因此我认为这将是更好的方法。

I'd say the actual name of your class ConcreteComponent1 is not "MyCompany.Components.ConcreteComponent1" because it includes a generic. Execute

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

to see the string representation for your class created by C#.

But why do you define your ConcreteComponent1 class the way you do? Wouldn't it be better to use something like this:

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

This way you can use the expected name you already used in your example and you can remove the extra private field your approach introduces. As your ConcreteComponent1 class doesn't really need any generic functionality this would be a better approach in my opinion.

无悔心 2024-10-16 02:17:28

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

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 构造函数一起使用。

First of all, actual name of your type is:

MyCompany.Components.ConcreteComponent1`1

It can't be instantiated because you have to specify type parameters:

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

this will work with internal constructor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文