使用反射动态实例化扩展基类的类 [英] Dynamically instantiate classes extending baseclass using reflection

查看:41
本文介绍了使用反射动态实例化扩展基类的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很长一段时间以来,我一直在努力寻找一种方法来动态实例化扩展特定基类的所有类(在运行时).从我读到的内容来看,它应该使用 Reflection 来完成,不幸的是我还没有弄清楚如何.

For a long time I have been struggling with finding a way to dynamically instantiate all classes that extends a specific baseclass (during runtime). From what I have read, it is supposed to be done using Reflection, unfortunately I haven't figured out how yet.

我的项目结构如下:

Library
--|
  |
  --Vehicle.cs (abstract class)
  |
  --Car.cs (extending vehicle)
  |
  --Bike.cs (extending vehicle)
  |
  --Scooter.cs (extending vehicle)
  |
  --InstanceService.cs (static class)
  |
  |
ConsoleApplication
--|
  |
  --Program.cs

InstanceService 类包含一个通用方法,该方法应该返回一个 IEnumerable,其中包含扩展 Vehicle 的实例化类,意思是 <代码>汽车、自行车和滑板车.

The InstanceService class contains a generic method which is supposed to return an IEnumerable<T> containing the instantiated classes extending Vehicle, meaning Car, Bike & Scooter.

下面发布的代码是 InstanceService 类的当前状态,在尝试了大量不同的解决方案后,这意味着它主要包含用于调试的工具.

The code posted bellow is the current state of the InstanceService class, after having tried a ton of different solutions, meaning it mostly contains tools for debugging.

InstanceService.cs

using System;
using System.Collections.Generic;

namespace Library
{
    public static class InstanceService<T>
    {
        //returns instances of all classes of type T
        public static IEnumerable<T> GetInstances()
        {

            var interfaceType = typeof(T);
            List<T> list = new List<T>();
            Console.WriteLine("Interface type: " + interfaceType.ToString());
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach(var assembly in assemblies)
            {
                Console.WriteLine("Assembly: " + assembly.ToString());
                if (assembly.GetType().IsAbstract)
                {
                    var instance = (T) Activator.CreateInstance(assembly.GetType());
                    list.Add(instance);
                }
            }
            return list;
        }
    }
}

我还附上了抽象 Vehicle 类的代码以及它的一个实现.

I have also attached the code for the abstract Vehicle class as well as one of the implementations of it.

Vehicle.cs

namespace Library
{
    public abstract class Vehicle
    {
        protected float maxSpeedInKmPerHour;
        protected float weightInKg;
        protected float priceInDkk;
    }
}

Car.cs

namespace Library
{
    public class Car : Vehicle
    {

        public Car()
        {
            this.maxSpeedInKmPerHour = 1200;
            this.weightInKg = 45000;
            this.priceInDkk = 71000000;
        }
    }
}

推荐答案

我认为您应该感兴趣的方法是 IsAssignableFrom.

I think the method that should interest you is IsAssignableFrom.

此外,如果允许使用 LINQ,代码会更容易,并且由于您一次创建一个对象,我建议使用 收益回报.

Also, the code is much easier with LINQ, if you're allowed to use that, and since you're creating the objects one at a time, I suggest using yield return.

static IEnumerable<T> GetInstances<T>() 
{
    var baseType = typeof(T);
    var types = AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany( a => a.GetTypes() )
        .Where
        (
            t => baseType.IsAssignableFrom(t)                  //Derives from base
              && !t.IsAbstract                                 //Is not abstract
              && (t.GetConstructor(Type.EmptyTypes) != null)   //Has default constructor
        );


    foreach (var t in types)
    {
        yield return (T)Activator.CreateInstance(t);
    }
}

或者,如果您出于某种原因炫耀,并且想用一句话来表达:

Or if for some reason you're showing off and you want to do it with one statement:

    var types = AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany( a => a.GetTypes() )
        .Where
        (
            t => typeof(T)IsAssignableFrom(t)  
              && !t.IsAbstract 
              && (t.GetConstructor(Type.EmptyTypes) != null) 
        )
        .Select
        (
            t => (T)Activator.CreateInstance(t)
        );

这篇关于使用反射动态实例化扩展基类的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆