从字符串名称在装配中创建类的实例字符串、实例、名称

2023-09-03 04:28:31 作者:卿酒

我不知道这是可能的,而且我很新的使用装配在C#.NET。

I'm not sure if this is possible, and I'm quite new to using assemblies in C#.NET.

我想要做的是,当提供的类的字符串名称创建一个类的实例。事情是这样的:

What I would like to do is to create an instance of a class when supplied the string name of that class. Something like this:

using MyAssembly;

namespace MyNameSpace
{
     Class MyClass
     {
          int MyValue1;
          int MyValue2;

          public MyClass(string myTypeName)
          {
               foreach(Type type in MyAssembly)
               {
                    if((string)type == myTypeName)
                    {
                         //create a new instance of the type
                    }
               }
               AssignInitialValues(//the type created above)
          }

          //Here I use an abstract type which the type above inherits from
          private void AssignInitialValues(AbstractType myClass)
          {
               this.value1 = myClass.value1;
               this.value2 = myClass.value2;
          }
      }
 }

显然,你不能比较字符串类型,但它说明了什么我想要做的:创建一个不同的装配发现从提供的字符串类型

Obviously you cannot compare strings to types but it illustrates what I'm trying to do: create a type found in a different assembly from a supplied string.

有什么想法?

编辑:

在尝试之后:

var myObject = (AbstractType) Activator.CreateInstance(null, myTypeName);
AssignInitialValues(myObject);

我得到了一些错误的:

I get a number of errors:

在可访问性不一致:参数类型MyAssembly.AbstractType'比方法进行访问少MyNameSpace.MyClass.AssignInitialValues​​(MyAssembly.AstractType)' 在MyAssembly.AstractType'不可访问,由于它的保护级别 的类型或命名空间名称MyAssembly程序'找不到(是否缺少using指令或程序集引用?) 的类型或命名空间名称AbstractType'找不到(是否缺少using指令或程序集引用?) Inconsistent accessibility: parameter type 'MyAssembly.AbstractType' is less accessible than method 'MyNameSpace.MyClass.AssignInitialValues(MyAssembly.AstractType)' 'MyAssembly.AstractType' is inaccessible due to it's protection level The type or namespace name 'MyAssembly' could not be found (are you missing a using directive or an assembly reference?) The type or namespace name 'AbstractType' could not be found (are you missing a using directive or an assembly reference?)

不知道是什么原因无法找到组件;我添加了一个参考组装和我使用using指令在装配的命名空间。至于保护级别,它调用类(或者说类的构造函数),这只能是公共的。

Not exactly sure why it can't find the assembly; I've added a reference to the assembly and I use a Using Directive for the namespace in the assembly. As for the protection level, it's calling classes (or rather the constructors of classes) which can only be public.

这是哪里的问题任何线索?

Any clues on where the problem is?

更新:

在寻找通过SO几篇文章我碰到这个: http://stackoverflow.com/a/1632609/360627 使得 AbstractType 类公众解决可访问性不一致的问题。

After looking through several articles on SO I came across this: http://stackoverflow.com/a/1632609/360627 Making the AbstractTypeclass public solved the issue of inconsistent accessibility.

新的编译器错误是这样的:

The new compiler error is this:

无法将类型System.Runtime.Remoting.ObjectHandle'到'MyAssembly.AbstractType

Cannot convert type 'System.Runtime.Remoting.ObjectHandle' to 'MyAssembly.AbstractType'

引用的线是这个:

var myObject = (AbstractType) Activator.CreateInstance(null, myTypeName);

使用 .Unwrap() GET是我过去的这个错误,我认为这是正确的方式来做到这一点(不确定)。但是,在运行该程序,然后我得到了这个时候code被称为TypeLoadException时。

Using .Unwrap() get's me past this error and I think it's the right way to do it (uncertain). However, when running the program I then get a TypeLoadException when this code is called.

TypeLoadException:未能从程序集myNameSpace对象加载类型AbstractType......

TypeLoadException: Could not load type ‘AbstractType’ from assembly ‘MyNameSpace'...

我马上可以发现,它寻找的类型是正确的,但它看起来在装配是错误的。仰望 Activator.CreateInstance(字符串,字符串)法透露,null作为第一个参数意味着该方法将查找在执行的程序集。这是违背了所需的行为在原岗位。

Right away I can spot that the type its looking for is correct but the assembly it's looking in is wrong. Looking up the Activator.CreateInstance(String, String) method revealed that the null as the first argument means that the method will look in the executing assembly. This is contrary to the required behavior as in the original post.

我已经试过用 MyAssembly程序作为第一个参数,但是这会产生错误:

I've tried using MyAssembly as the first argument but this produces the error:

MyAssembly程序是一个空间,但使用类似变量

'MyAssembly' is a 'namespace' but is used like a 'variable'

我的认为的,这是由 MyAssembly程序不是字符串。但是,如果我尝试MyAssembly程序我得到以下编译器错误:

I think that this is caused by MyAssembly not being a string. However if I try 'MyAssembly' I get the following compiler errors:

在字符文字字符太多 的最佳重载方法匹配'System.Activator.CreateInstance(System.Activati​​onContext,字符串[])'有一些无效参数 参数1:不能从'符'转换为'System.Activati​​onContext 参数2:无法从字符串转换为字符串[]' Too many characters in character literal The best overloaded method match for 'System.Activator.CreateInstance(System.ActivationContext, string[])' has some invalid arguments Argument 1: cannot convert from 'char' to 'System.ActivationContext' Argument 2: cannot convert from 'string' to 'string[]'

在我看来,像它试图用错误的过载。

Seems to me like it's trying to use the wrong overload.

在如何解决这一问题有什么想法?

Any thoughts on how to fix this?

推荐答案

好了,这就是答案。我已经用实际code测试,它的工作原理。我不知道这是否是最好的方法还是最有效的方式。我upvoted其他两个答案,因为他们帮助我得到正轨,但这里是完整的答案。

Okay so this is the answer. I've tested it using real code and it works. I'm not sure if it's the best way or the most efficient way. I've upvoted the other two answers because they helped me get onto the right track but here is the full answer.

using MyAssembly;

namespace MyNameSpace
{
     Class MyClass
     {
          int MyValue1;
          int MyValue2;

          public MyClass(string myTypeName)
          {
               string assemblyName = Assembly.GetAssembly(typeof(AbstractType)).ToString();
               AbstractType selectedClass = (AbstractType)Activator.CreateInstance(assemblyName, myTypeName).Unwrap();
               AssignInitialValues(selectedClass);
          }

          private void AssignInitialValues(AbstractType myClass)
          {
               this.value1 = myClass.value1;
               this.value2 = myClass.value2;
          }
      }
 }

花了谷歌搜索的我三天,寻遍SO和MSDN,但它就在那里。 需要注意的是实例化一个类 Activator.CreateInstance(字符串,字符串)程序集的名称(第一个参数)时,必须是完整的程序集名称.dll文件的不只是名字(或.exe)。

Took me three days of googling, searching through SO and MSDN but there it is. Note that when instantiating a class with Activator.CreateInstance(String, String) the assembly name (first parameter) must be the full assembly name not just the name of the .dll (or .exe).

集名称可以使用字符串的AssemblyName = Assembly.GetAssembly(typeof运算(AbstractType))进行检索的ToString(); ,其中 AbstractType 可你知道被遏制,在装配中定义的类型来代替。

The assembly name can be retrieved by using string assemblyName = Assembly.GetAssembly(typeof(AbstractType)).ToString(); where AbstractType can be replaced by a type you know to be contained and defined in the assembly.

类型名称(第二个参数)必须是完全合格的名称,而不仅仅是类名。

The type name (second parameter) must be the fully qualified name, not just the class name.