C# 如何动态实例化一个类?

C# 如何动态实例化一个类?,c#,C#,Drv{id}是我的命名空间,Fonte是类名 为什么“type”总是空的 当我拨打第三条线路时,我得到: System.ArgumentNullException:'值不能为null。' 您需要这个。如上文所述 示例(来自MSDN链接): TopNamespace.SubNameSpace.ContainingClass+NestedClass,MyAssembly 你需要这个。如上文所述 示例(来自MSDN链接): TopNamespace.SubNameSpace.ContainingC

Drv{id}是我的命名空间,Fonte是类名

为什么“type”总是空的

当我拨打第三条线路时,我得到:

System.ArgumentNullException:'值不能为null。'

您需要这个。如上文所述

示例(来自MSDN链接):

TopNamespace.SubNameSpace.ContainingClass+NestedClass,MyAssembly

你需要这个。如上文所述

示例(来自MSDN链接):

TopNamespace.SubNameSpace.ContainingClass+NestedClass,MyAssembly


用于实例化类型的字符串格式错误

Type.GetType(String)
的文档中:

typeName:String

要获取的类型的程序集限定名。看见 . 如果类型位于当前正在执行的 在Mscorlib.dll中,提供类型名就足够了 由其命名空间限定

资料来源:

AssemblyQualifiedName
的文档中:

类型的程序集限定名由类型名组成, 包括其名称空间,后跟逗号,后跟显示 程序集的名称。获取程序集的显示名称 使用Assembly.FullName属性

例如,类的程序集限定名称可能如下所示 这:

TopNamespace.SubNameSpace.ContainingClass+NestedClass,MyAssembly, 版本=1.3.0.0,区域性=中性,PublicKeyToken=b17a5c561934e089


用于实例化类型的字符串格式错误

Type.GetType(String)
的文档中:

typeName:String

要获取的类型的程序集限定名。看见 . 如果类型位于当前正在执行的 在Mscorlib.dll中,提供类型名就足够了 由其命名空间限定

资料来源:

AssemblyQualifiedName
的文档中:

类型的程序集限定名由类型名组成, 包括其名称空间,后跟逗号,后跟显示 程序集的名称。获取程序集的显示名称 使用Assembly.FullName属性

例如,类的程序集限定名称可能如下所示 这:

TopNamespace.SubNameSpace.ContainingClass+NestedClass,MyAssembly, 版本=1.3.0.0,区域性=中性,PublicKeyToken=b17a5c561934e089


我最近写了一些代码。像您一样,我需要在运行时实例化一个对象,但在类的位置上遇到了几个问题(不同的程序集,以vshost运行,以IISExpress运行)

这是一个非常通用的场景,所以对于您的需求来说可能有些过分了

var typeName = $"Drv{id}.Fonte";
var type = Type.GetType(typeName);
var myObject = Activator.CreateInstance(type);
它将返回null或可用于
Activator.CreateInstance()
的类型,并且您知道它是可访问的。在您的情况下,将代码更改为

private static Type GetType(string typeName)
{
    // check executing assembly
    var type = Assembly
        .GetExecutingAssembly()
        .GetTypes()
        .FirstOrDefault(x => x.FullName == typeName);

    // if not found check referenced assemblies
    if (type == null)
    {
        type = Assembly
            .GetExecutingAssembly()
            .GetReferencedAssemblies()
            .Select(Assembly.Load)
            .SelectMany(x => x.GetTypes())
            .FirstOrDefault(x => x.FullName == typeName);
    }

    // if still not found check all suitably named assemblies in executing folder
    if (type == null)
    {
        var files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll");

        if (files.Length == 0)
        {
            files = Directory.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath, "*.dll");
        }

        files.ToList().ForEach(filename =>
        {
            if (type == null)
            {
                var assembly = Assembly.LoadFile(filename);
                var castableAssembly = AppDomain.CurrentDomain.Load(assembly.GetName());
                type = castableAssembly.GetTypes().FirstOrDefault(x => x.FullName == typeName);
            }
        });
    }

    return type;
}

这不是性能友好的代码,但除非您经常这样做,或者您的工作目录中有大量程序集,否则您不必担心它。如果您经常这样做,或者您确实有一吨的组件,那么您应该重新考虑总体设计。

有我最近编写的这段代码。像您一样,我需要在运行时实例化一个对象,但在类的位置上遇到了几个问题(不同的程序集,以vshost运行,以IISExpress运行)

这是一个非常通用的场景,所以对于您的需求来说可能有些过分了

var typeName = $"Drv{id}.Fonte";
var type = Type.GetType(typeName);
var myObject = Activator.CreateInstance(type);
它将返回null或可用于
Activator.CreateInstance()
的类型,并且您知道它是可访问的。在您的情况下,将代码更改为

private static Type GetType(string typeName)
{
    // check executing assembly
    var type = Assembly
        .GetExecutingAssembly()
        .GetTypes()
        .FirstOrDefault(x => x.FullName == typeName);

    // if not found check referenced assemblies
    if (type == null)
    {
        type = Assembly
            .GetExecutingAssembly()
            .GetReferencedAssemblies()
            .Select(Assembly.Load)
            .SelectMany(x => x.GetTypes())
            .FirstOrDefault(x => x.FullName == typeName);
    }

    // if still not found check all suitably named assemblies in executing folder
    if (type == null)
    {
        var files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll");

        if (files.Length == 0)
        {
            files = Directory.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath, "*.dll");
        }

        files.ToList().ForEach(filename =>
        {
            if (type == null)
            {
                var assembly = Assembly.LoadFile(filename);
                var castableAssembly = AppDomain.CurrentDomain.Load(assembly.GetName());
                type = castableAssembly.GetTypes().FirstOrDefault(x => x.FullName == typeName);
            }
        });
    }

    return type;
}

这不是性能友好的代码,但除非您经常这样做,或者您的工作目录中有大量程序集,否则您不必担心它。如果您经常这样做,或者您确实有一吨组件,那么您应该重新考虑整体设计。

我将详细介绍实际部分

正如其他人所说,您需要程序集限定名。 为什么?我们来看一下
Type.GetType(string typeName)
方法的注释

参数:

//类型名称:
//要获取的类型的程序集限定名。请参阅System.Type.AssemblyQualifiedName

//如果类型位于当前正在执行的程序集中或Mscorlib.dll中,则只需提供由其命名空间限定的类型名即可

请注意,只有当类型位于当前执行的程序集中时,才足以像您那样调用它

我在另一个项目中有一个类,它被我的主项目引用,就像你一样

var typeName = $"Drv{id}.Fonte";
var type = GetType(typeName); // using the above method
var myObject = Activator.CreateInstance(type);
然后我这样称呼它:

using System.Reflection;

namespace Test2
{
    public class Class1
    {
        public string CallMe()
        {
            return Assembly.GetExecutingAssembly().FullName;
        }
    }
}

我希望您能看到区别在哪里,以及为什么现在需要提供限定名称。

我将详细说明实际部分

正如其他人所说,您需要程序集限定名。 为什么?我们来看一下
Type.GetType(string typeName)
方法的注释

参数:

//类型名称:
//要获取的类型的程序集限定名。请参阅System.Type.AssemblyQualifiedName

//如果类型位于当前正在执行的程序集中或Mscorlib.dll中,则只需提供由其命名空间限定的类型名即可

请注意,只有当类型位于当前执行的程序集中时,才足以像您那样调用它

我在另一个项目中有一个类,它被我的主项目引用,就像你一样

var typeName = $"Drv{id}.Fonte";
var type = GetType(typeName); // using the above method
var myObject = Activator.CreateInstance(type);
然后我这样称呼它:

using System.Reflection;

namespace Test2
{
    public class Class1
    {
        public string CallMe()
        {
            return Assembly.GetExecutingAssembly().FullName;
        }
    }
}

我希望您能看到区别所在,以及为什么现在需要提供限定名。

您的所有类型都在同一个程序集中编译吗?我是说在当前正在执行的程序集中?如果没有,那么您需要首先获取程序集,然后从中获取类型。是的。如果我键入Drv1.Fonte,则自动完成会起作用