C# 获取继承接口的类

本文介绍了如何利用C#的反射和LINQ查询在运行时获取当前程序集下实现IManager接口的所有类,并演示了如何遍历这些类并调用它们的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原理

利用反射获取当前程序集下的所有类型使用LINQ 查询实现接口的类,并将结果转换为列表

 1. 关键代码

// 获取当前正在执行的程序集
        var implementingClasses = Assembly.GetExecutingAssembly().GetTypes()
            // 选择实现了 IManager 接口的类型
            .Where(t => t.GetInterfaces().Contains(typeof(IManager)))
            // 将符合条件的类型转换为列表
            .ToList();

 2. 示例代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;

public class Manager :MonoBehaviour
{
    private List<Type> m_ImplementingClasses;
    public void Start()
    {
        // 获取当前正在执行的程序集
        m_ImplementingClasses = Assembly.GetExecutingAssembly().GetTypes()
            // 选择实现了 IManager 接口的类型
            .Where(t => t.GetInterfaces().Contains(typeof(IManager)))
            // 将符合条件的类型转换为列表
            .ToList();


        foreach (var implementingClass in m_ImplementingClasses.Where(implementingClass => implementingClass.Name == nameof(TestManager)))
        {
            implementingClass.GetMethod("Init")?.Invoke(null, new object[]{"测试"});
        }
    }
}


public class TestManager : IManager
{
    public static void Init(string message)
    {
        Debug.Log($"I am SAA {message}");
    }
}

public interface IManager
{
    
}

3. 运行结果 

### C#接口继承继承的区别及优势 #### 区别 1. **定义方式** - 接口中只包含方法、属性、事件或索引器的声明,不包含具体实现[^2]。它们用于定义一组契约,强制实现该接口遵循特定的行为模式。 - 抽象可以包含部分实现代码,也可以包含完全未实现的方法(即抽象方法)。派生可以选择性地覆盖某些方法,同时保留其他方法的默认实现[^4]。 2. **多重继承** - 在 C# 中,一个可以从多个接口继承,这使得接口成为实现多重继承的主要手段之一[^2]。这种能力允许单个组合多种不同的行为特征。 - 而继承仅支持单一继承,也就是说一个只能从一个基继承[^3]。 3. **灵活性** - 接口提供了更高的灵活性,因为可以在任何时候引入新接口并将其应用于现有,而无需更改已有代码结构[^5]。 - 抽象虽然也具备一定的扩展性和可维护性,但在设计阶段就需要考虑好其层次结构,后期调整成本较高。 4. **用途侧重点** - 接口主要关注于“做什么”,强调外部可见的功能集合;适合用来表达某种角色或者职责[^5]。 - 抽象除了规定子应该完成的任务外,还可能提供基础版本的具体操作逻辑,因此更适合表示“是什么”的概念模型[^5]。 #### 优势 ##### 接口继承的优势 - **解耦合** 使用接口可以让不同模块间保持较低程度的相关度,促进软件组件间的独立开发和测试。 - **增强重用性** 多个无关联的对象可以通过共同遵守某个接口标准达到资源共享的目的,比如各种形状都可以共享绘图功能[^2]。 - **支持动态绑定** 当程序运行时可以根据实际需求创建满足指定接口的不同类型的实例,增加了应用程序适应变化的能力。 ##### 继承的优势 - **代码复用** 子可以直接利用父已经存在的字段、方法等功能单元,在此基础上做进一步定制化处理[^4]。 - **自然建模现实世界关系** 对应自然界中存在的父子辈分现象,采用继承能够直观反映事物之间的内在联系。 以下是展示如何应用这两种机制的一个简单例子: ```csharp // 定义一个通用接口 IAnimal public interface IAnimal { void MakeSound(); } // 创建两个实现了IAnimal接口的具体动物类型 public class Dog : IAnimal { public void MakeSound() => Console.WriteLine("Woof!"); } public class Cat : IAnimal { public void MakeSound() => Console.WriteLine("Meow!"); } // 基础哺乳动物别 BaseMammal (作为抽象) abstract public class Mammal { protected string Name; // 构造函数初始化名字变量 public Mammal(string name){ this.Name = name; } // 提供公共读取名称的方法 public virtual string GetName(){ return $"The animal's name is {Name}."; } } // 继承自Mammal, 并且额外添加了年龄信息管理 class HumanBeing:Mammal{ private int Age; // 新增设置人年龄的方法 public void SetAge(int age){ if(age >=0 )this.Age=age; else throw new ArgumentException("Invalid value."); } // 重载获取基本信息的方法加入显示年龄的内容 override public string GetName(){ return base.GetName()+$" And its age is {Age}."; } } ``` #### 结论 综上所述,选择使用接口还是抽象取决于项目具体情况下的业务需求分析结果。如果仅仅是为了规范各个参与者的行为表现,则优先选用接口形式;若是希望构建起一套完整的实体体系框架,则倾向于运用抽象途径[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天喝水了嘛.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值