导读:本期聚焦于小伙伴创作的《C#如何创建和使用DLL?动态链接库开发与调用详解》,敬请观看详情。把功能封装成DLL后,主程序体积更小且模块可复用,但不少人在类库目标框架不一致时调用失败。本文从类库创建讲起,说明如何用Visual Studio生成.dll文件,再通过添加引用的方式在控制台项目里调用公共方法。你会看到强命名、依赖项拷贝以及平台目标设置等实际开发中必须处理的细节,避免在部署时出现找不到入口点或版本冲突的问题。

在C#项目中把可复用的逻辑编译成DLL(动态链接库),可以让多个应用程序共享同一份代码,也便于团队分工维护。下面直接说明从建库到调用的完整过程。

一、创建C#类库项目

打开Visual Studio,选择“创建新项目”,在项目模板中搜索“类库”,注意要选择“类库(.NET Framework)”或“类库(.NET Core/.NET)”对应你实际运行环境。类库项目编译后不会产生可执行文件,而是输出一个.dll文件。

新建类库后,默认会生成一个Class1.cs。我们把它改成一个有实际意义的计算工具类,并标记为public,否则外部程序无法引用其中的成员。以下代码演示了一个简单的数学工具类库。

// 数学工具类库,编译后生成 MathLib.dll
using System;

namespace MathLib
{
    public class Calculator
    {
        // 求和
        public int Add(int a, int b)
        {
            return a + b;
        }

        // 获取当前时间字符串
        public string NowString()
        {
            return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }
    }
}

在解决方案配置中选择“Release”模式,右键项目点击“生成”,Visual Studio会在输出目录(如binReleasenet6.0)下生成MathLib.dll。这个文件就是动态链接库。

需要注意,类库的目标框架(Target Framework)必须与调用方保持一致或兼容。例如调用程序是.NET 6,类库也应该是.NET 6或.NET Standard 2.0,否则添加引用时会提示框架不兼容。

二、在C#项目中引用并调用DLL

新建一个控制台应用作为调用方,在“解决方案资源管理器”中右键“依赖项”或“引用”,选择“添加项目引用”可直接引用同一解决方案下的类库;如果是外部DLL,则选择“浏览”找到MathLib.dll文件。

添加引用后,在代码中通过using引入命名空间即可使用。下面代码展示了控制台程序如何调用刚才生成的DLL中的方法。

using System;
using MathLib; // 引入DLL中的命名空间

class Program
{
    static void Main()
    {
        Calculator calc = new Calculator();
        int result = calc.Add(3, 5);
        Console.WriteLine("3 + 5 = " + result);
        Console.WriteLine("当前时间:" + calc.NowString());
    }
}

编译并运行控制台程序,若输出结果为“3 + 5 = 8”及时间字符串,说明DLL调用成功。这种方式的优势在于,若后续Calculator逻辑变更,只需替换MathLib.dll而不用重新编译主程序(在接口不变的前提下)。

如果DLL还依赖其他第三方库,那些依赖的.dll也要一同拷贝到主程序输出目录,否则运行时会抛出“未能加载文件或程序集”的异常。

三、通过反射动态加载DLL

除了静态添加引用,C#还支持在运行时通过反射加载DLL,这在插件化架构中很常见。使用Assembly.LoadFrom方法可以指定路径加载,再创建实例并调用方法。

以下示例展示如何从指定路径动态加载MathLib.dll并调用Add方法,无需在编译期引用。

using System;
using System.Reflection;

class DynamicLoader
{
    static void Run()
    {
        // 加载位于程序目录下的DLL
        Assembly asm = Assembly.LoadFrom("MathLib.dll");
        Type type = asm.GetType("MathLib.Calculator");
        object instance = Activator.CreateInstance(type);
        MethodInfo method = type.GetMethod("Add");
        int r = (int)method.Invoke(instance, new object[] { 10, 20 });
        Console.WriteLine("动态调用结果:" + r);
    }
}

反射调用的灵活性高,但性能略低于直接引用,且绕过了编译期类型检查,代码健壮性需自行保证。在固定依赖场景中,优先使用静态引用方式。

若希望DLL具备强命名(防止版本冲突、支持放入GAC),需要在项目属性中生成密钥文件(.snk),并对程序集进行签名。强命名后的DLL在被引用时会校验公钥,能有效避免“DLL地狱”问题。

四、常见错误与排查

开发中常遇到“找不到类型或命名空间”的编译错误,多数情况是忘了添加引用或using语句。若运行时报BadImageFormatException,通常是平台目标不匹配,比如主程序是Any CPU但DLL是x86,需在项目属性中统一平台目标。

另一个易错点是把内部类(internal)当作public暴露,外部工程无法访问。务必确认需要导出的类型和方法都标有public修饰符,且所在程序集未设置InternalsVisibleTo限制。

问题现象可能原因解决办法
CS0246 找不到类型未添加引用或using添加DLL引用并写using
FileNotFoundExceptionDLL未拷贝到输出目录检查生成事件或手动复制
BadImageFormatException平台目标不一致统一x86/x64/Any CPU

掌握上述创建、引用、动态加载与排错方法后,你就能在C#中规范地使用DLL来拆分和复用代码模块,提升工程的可维护性与部署效率。

C#DLL动态链接库修改时间:2026-08-03 23:45:23

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。