为了账号安全,请及时绑定邮箱和手机立即绑定

如何获取类列表,从一个类和一个接口继承/或从两个接口继承

如何获取类列表,从一个类和一个接口继承/或从两个接口继承

C#
守着星空守着你 2023-07-09 17:53:44
我想创建基类的默认后代实例的列表。我已经可以获得的是那些后代的一个List<Type>或IEnumerable<Type>多个。基类和后代都是自制的。所以我非常理解他们。C# 框架是否已经为此提供了一种智能方法?这就是我得到的:    public static List<Type> GetList_Descendants(Type baseClassType, string assemblyName)    {        return Assembly        .GetAssembly(baseClassType)        .GetTypes()        .Where(t => t.IsSubclassOf(baseClassType))        .ToList(); // Otherwise return would be of type IEnumerable.    }    public static void Add_AllDescendants<T>(this List<T> emptySource, List<Type> descendants)        where T : new()    {        emptySource.AddRange(???);    }类的后代 && 接口stop-cran已经给了我一个答案,关于如何获取泛型类型给出的类的后代。(请参阅下面的第一个答案和前两个评论。)两个接口的后代我怎样才能获得两个接口的后代?这就是我所做的,它的工作原理:    /// <summary>    /// Assumes, that there are two interfaces and classes inheriting of both - all placed in the same assembly.    /// 1st interface is IStrategy. 2nd interface is described by generic type.    ///     /// Creates an IEnumerable of all available Func'IStrategy' child instances which are of generic type, too.    /// Thus one decouple creation of such a IEnumerable from creating the child classes of type IStrategy.    /// </summary>    /// <typeparam name="T"></typeparam>    /// <returns></returns>    public static IEnumerable<Func<IStrategy>> GetByInterfaceBaseType<T>() =>    typeof(T)    .Module    .Assembly    .GetTypes()    .Where(t => (t.GetInterface(typeof(T).FullName)!= null)             && (t.GetInterface(nameof(IStrategy)) != null))    // We assume T has a parameterless constructor    .Select(t => (Func<IStrategy>)(() => (IStrategy)Activator.CreateInstance(t)));对我来说,这个案子已经解决了。但好的建议总是受欢迎的!
查看完整描述

1 回答

?
手掌心

TA贡献1942条经验 获得超3个赞

考虑到问题评论,我建议有一个IStrategy接口并用于IEnumerable<Func<IStrategy>>注入策略工厂列表(这里为了简洁起见我使用委托工厂,可以使用接口代替)。因此,我们可以将创建这样一个列表与创建策略脱钩:


static IEnumerable<IStrategy> CreateAll(this IEnumerable<Func<IStrategy>> factories) =>

    factories.Select(factory => factory());

使用示例:


listOfStrategies.AddRange(

    new Func<IStrategy>[]

    {

        () => new B(),

        () => new C()

    }).CreateAll()); // 2 items (`B` and `C`) will be added.

Func<IStrategy>如果方便的话,可以从类层次结构中创建策略工厂列表 ( ):


static IEnumerable<Func<IStrategy>> GetByBaseType<T>() =>

    typeof(T)

        .Assembly

        .GetTypes()

        .Where(t => t.IsSubclassOf(typeof(T)) && t.GetInterface(nameof(IStrategy)) != null)

        // We assume t has a parameterless constructor

        .Select(t => (Func<IStrategy>)(() => (IStrategy)Activator.CreateInstance(t)));

一个样品:


class A { }


class B : A, IStrategy { }


class C : A, IStrategy { }

创建策略工厂列表:


var factories = GetByBaseType<A>().ToList(); // Two `Func<IStrategy>` objects

var strategies = CreateAll(factories).ToList(); // Two `IStrategy` objects - `B` and `C`.

此外,通常返回的方法比接受并向其中添加项目的IEnumerable<T>方法更具可重用性和“纯粹”性。List<T>


还有一件事 - 许多 DI 容器支持解析所有已注册实现的列表。请参阅UnityContainer下面的示例:


var c = new UnityContainer()

    .RegisterType<IStrategy, B>("B")

    .RegisterType<IStrategy, C>("C");


// Two items - `B` and `C`.

c.Resolve<IEnumerable<IStrategy>>().ToList();


查看完整回答
反对 回复 2023-07-09
  • 1 回答
  • 0 关注
  • 102 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信