C# 如何动态实例化一个类?
Drv{id}是我的命名空间,Fonte是类名 为什么“type”总是空的 当我拨打第三条线路时,我得到: System.ArgumentNullException:'值不能为null。' 您需要这个。如上文所述 示例(来自MSDN链接): TopNamespace.SubNameSpace.ContainingClass+NestedClass,MyAssembly 你需要这个。如上文所述 示例(来自MSDN链接): TopNamespace.SubNameSpace.ContainingClass+NestedClass,MyAssemblyC# 如何动态实例化一个类?,c#,C#,Drv{id}是我的命名空间,Fonte是类名 为什么“type”总是空的 当我拨打第三条线路时,我得到: System.ArgumentNullException:'值不能为null。' 您需要这个。如上文所述 示例(来自MSDN链接): TopNamespace.SubNameSpace.ContainingClass+NestedClass,MyAssembly 你需要这个。如上文所述 示例(来自MSDN链接): TopNamespace.SubNameSpace.ContainingC
用于实例化类型的字符串格式错误 从
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,则自动完成会起作用