在C#开发中,动态根据类名创建实例是一个常见的需求,比如从配置文件读取类名后生成对应对象,或者实现插件化的对象加载,这时候就需要用到反射技术。下面我们就一步步讲解具体的实现方法。

一、反射创建实例的核心基础
要实现根据类名创建实例,核心需要用到两个关键类:Type类和Activator类。Type类用来获取目标类的类型信息,Activator类则提供了创建对象实例的方法。首先我们需要知道目标类所在的程序集,因为类的类型信息需要从对应程序集中获取。
1. 获取Type对象的两种方式
如果已知类所在的程序集,并且类名是完整的限定名(包含命名空间),可以直接通过Type.GetType方法获取Type对象;如果只知道类名和所在程序集,也可以通过程序集的GetType方法获取。
下面是获取Type的示例代码:
using System;
namespace ReflectionDemo
{
public class TestClass
{
public string Name { get; set; }
public TestClass() { }
public TestClass(string name)
{
Name = name;
}
}
class Program
{
static void Main(string[] args)
{
// 方式1:使用Type.GetType,参数是类的完整限定名(命名空间+类名)
// 如果类在当前程序集,直接传入完整限定名即可
Type type1 = Type.GetType("ReflectionDemo.TestClass");
// 方式2:如果知道程序集,也可以通过程序集获取Type
// 先获取当前程序集,再从程序集中获取指定类名的Type
var assembly = typeof(Program).Assembly;
Type type2 = assembly.GetType("ReflectionDemo.TestClass");
Console.WriteLine($"type1是否为空:{type1 == null}");
Console.WriteLine($"type2是否为空:{type2 == null}");
}
}
}2. 使用Activator创建实例
获取到Type对象之后,就可以使用Activator.CreateInstance方法创建实例,该方法支持无参构造函数和有参构造函数的场景。
(1)调用无参构造函数创建实例
如果目标类有无参构造函数,直接调用Activator.CreateInstance(Type type)即可,返回的是object类型的实例,需要强制转换为目标类型。
using System;
namespace ReflectionDemo
{
public class TestClass
{
public string Name { get; set; }
public TestClass()
{
Name = "默认名称";
}
}
class Program
{
static void Main(string[] args)
{
// 获取TestClass的Type对象
Type targetType = Type.GetType("ReflectionDemo.TestClass");
if (targetType != null)
{
// 创建实例,调用无参构造函数
object instanceObj = Activator.CreateInstance(targetType);
// 强制转换为目标类型
TestClass instance = instanceObj as TestClass;
if (instance != null)
{
Console.WriteLine($"创建实例成功,Name属性值:{instance.Name}");
}
}
}
}
}(2)调用有参构造函数创建实例
如果目标类的构造函数需要参数,可以在Activator.CreateInstance的第二个参数传入参数数组,参数顺序需要和构造函数的参数顺序一致。
using System;
namespace ReflectionDemo
{
public class TestClass
{
public string Name { get; set; }
public TestClass(string name)
{
Name = name;
}
}
class Program
{
static void Main(string[] args)
{
Type targetType = Type.GetType("ReflectionDemo.TestClass");
if (targetType != null)
{
// 构造函数的参数是"测试名称",传入参数数组
object instanceObj = Activator.CreateInstance(targetType, new object[] { "测试名称" });
TestClass instance = instanceObj as TestClass;
if (instance != null)
{
Console.WriteLine($"创建实例成功,Name属性值:{instance.Name}");
}
}
}
}
}二、常见问题与注意事项
- 类名必须是完整限定名:使用
Type.GetType时,如果类不在当前程序集或者mscorlib中,需要传入包含程序集信息的完整限定名,格式为命名空间.类名, 程序集名称,例如ReflectionDemo.TestClass, ReflectionDemo。 - 构造函数访问权限:如果目标类的构造函数是私有的,需要使用
Activator.CreateInstance的重载方法,指定nonPublic参数为true,比如Activator.CreateInstance(targetType, true),但这种方式不建议常规使用,会破坏封装性。 - 类型转换安全:创建实例后转换为目标类型时,建议使用as运算符,避免直接强制转换抛出InvalidCastException异常。
- 性能问题:反射创建实例的性能比直接new要低,如果高频创建对象,可以考虑缓存Type对象,减少重复获取Type的开销。
三、完整示例演示
下面是一个从配置读取类名,动态创建实例的完整示例:
using System;
using System.Configuration;
namespace ReflectionDemo
{
public interface ILogger
{
void Log(string message);
}
public class FileLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine($"文件日志:{message}");
}
}
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine($"控制台日志:{message}");
}
}
class Program
{
static void Main(string[] args)
{
// 假设从配置读取类名,这里模拟配置内容
string loggerClassName = "ReflectionDemo.ConsoleLogger";
Type loggerType = Type.GetType(loggerClassName);
if (loggerType != null && typeof(ILogger).IsAssignableFrom(loggerType))
{
ILogger logger = Activator.CreateInstance(loggerType) as ILogger;
if (logger != null)
{
logger.Log("这是一条测试日志");
}
}
else
{
Console.WriteLine("未找到对应的日志类或者类型不匹配");
}
}
}
}以上就是C#中利用反射根据类名创建实例对象的完整介绍,实际使用时可以根据具体场景调整获取Type和创建实例的方式,同时注意相关的注意事项,避免出现问题。
C#反射类名创建实例Activator类Type类修改时间:2026-05-29 03:51:53