查找从特定基类派生的所有类,并将它们添加到注册表中

本文关键字:添加 注册表 基类 派生 查找 | 更新日期: 2023-09-27 18:26:38

我有一个名为BaseStatus的基类,它看起来像这样:

 public class BaseStatus
    {       
        public int UnitId { get; protected set; }
        public UInt16 StatusValue { get; protected set; }
        public string StatusCode { get; protected set; }
        public string StatusDescription { get; protected set; }
        public BaseStatus()
        {
            this.UnitId = -1;
            this.StatusValue = 0;
            this.StatusCode = null;
            this.StatusDescription = null;
        }
}

此外,我有两个或多个其他基类,它们从BaseStatus派生并定义其他单元id。例如,这两个类

public class BaseGlobalStatus : BaseStatus
    {  
        public BaseGlobalStatus()
        {
            base.UnitId = -1;
        }
    }
    public class BaseGcmGdmStatus : BaseStatus
    {
        public BaseGcmGdmStatus()
        {
            base.UnitId = 2;
        }
    }
    public class BaseCcuStatus : BaseStatus
    {
        public BaseCcuStatus()
        {
            base.UnitId = 1;
        }
    }

背景是,我想从例如BaseCcuStatus派生,并在派生类中具有正确的UnitId。

现在我定义了正确的状态类,例如:

public class StatStErrDefinition : BaseGlobalStatus
    {
        public StatStErrDefinition()
            : base()
        {
            base.StatusDescription = "Kommando nicht zulässig, unit im state ERROR";
            base.StatusCode = "STAT_ST_ERR";
            base.StatusValue = 3;
        }
    }
    public class GcmStErrDefinition : BaseGcmGdmStatus
    {
        public GcmStErrDefinition()
            : base()
        {
            base.StatusDescription = "Kommando nicht zulässig, unit im state ERROR";
            base.StatusCode = "STAT_ST_ERR";
            base.StatusValue = 3;
        }
    }
    public class CcuStErrDefinition : BaseCcuStatus
    {
        public CcuStErrDefinition()
            : base()
        {
            base.StatusDescription = "Kommando nicht zulässig, unit im state ERROR";
            base.StatusCode = "STAT_ST_ERR";
            base.StatusValue = 3;
        }
    }

据我所知,StatStErrDefinition、GcmStErrDefinition和CcuStErrDefine这三个类应该具有在派生基类中设置的UnitId?

既然我已经定义了我的三个状态类,我想把它们放到注册表中。目前我正在使用这段代码来尝试获取它们。问题是结果中没有项目。

  registry = new StatusDictionary<UInt16, BaseStatus>();
                    var unitStatus = typeof(BaseStatus)
                                    .Assembly.GetTypes()
                                    .Where(x => x.BaseType == typeof(BaseStatus))
                                    .Select(x => new 
                                                { 
                                                    StatusType = x, 
                                                    UnitId = x.GetProperty("UnitId", BindingFlags.Public) 
                                                    StatVal = x.GetProperty("StatusValue", BindingFlags.Public) 
                                                }
                                            )
                                    .Where(x => x.StatVal != null && x.UnitId != null)
                                    .Select(x => new
                                    {
                                        UnitId = (int)x.UnitId.GetValue(null, null),
                                        StatusValue = (UInt16)x.StatVal.GetValue(null, null),
                                        Factory = (Func<BaseStatus>)(() => ((BaseStatus)Activator.CreateInstance(x.StatusType)))
                                    });

                    try
                    {
                        foreach (var status in unitStatus)
                        {
                            if (status.UnitId == unitId 
                                || status.UnitId < 0)
                                registry.Register(status.StatusValue, status.Factory);
                        }
                    }
                    catch (Exception ex)
                    {
                        string temp = ex.Message;
                    }

在LINQ表达式之后,var unitStatus为空。。。

稍后,注册表调用看起来像这样来获取特定的类,但在这一点上并不重要:

  stat = StatusContainer.GetRegistry(this.unitTypeId).GetInstance(this.StatusValue);

供参考:我想通过unittypeid和特定的状态值获得应该在注册表中的状态类。目前我的注册表方法不起作用,因为他找不到任何类。所以一定是哪里出了错。提前感谢

#更新1

我稍微改变了一下我的功能:

 registry = new StatusDictionary<UInt16, BaseStatus>();

                        //get all types of cucrent assembly
                        var allAssemblyTypes = Assembly.GetCallingAssembly().GetTypes();
                        //get all types from base status
                        var baseStatusTypes = allAssemblyTypes.Where(x => x.BaseType == typeof(BaseStatus));
                        //Place all concrete types in the foundtypes
                        List<Type> foundTypes = new List<Type>();
                        foreach (Type item in baseStatusTypes)
                        {
                            var temp = allAssemblyTypes.Where(x => x.BaseType == item)
                                         .Select(x => new
                                                {
                                                    StatusType = x,
                                                    UnitId = x.GetProperty("UnitId", BindingFlags.Public),
                                                    StatVal = x.GetProperty("StatusValue", BindingFlags.Public),
                                                }
                                            );
                        }

Temp现在包含正确的类型。问题是,如果temp是StatStErrDefinition类型,则StatusValue和UnitId属性为null。事实上,这些成员都是实例成员。有没有办法让它们发挥价值?

查找从特定基类派生的所有类,并将它们添加到注册表中

首先,您的LINQ查询相当长。将其分为不同的步骤,并将其存储在不同的变量中(或者用它们创建属性,无论你喜欢什么)

这是

  1. 易于阅读/维护
  2. 易于调试

有了这个,我认为你能够解决你的问题:)

要检查类是否为特定类型,可以使用方法.OfType

使用此方法获取值。请注意,您必须在您的案例中创建一个实例,因为构造函数中的值发生了更改。

 public static object GetPropValue(Type src, string propName)
 {
     var prop = src.GetProperty(propName);
     var instance = Activator.CreateInstance(src);
     var value = prop.GetValue(instance);
     return value;
 }

代替

UnitId = x.GetProperty("UnitId", BindingFlags.Public),

使用

UnitId = GetPropValue(x,"UnitId"),