Намерете всички класове, които произлизат от определен базов клас и ги добавете към регистъра

Имам базов клас, наречен 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 и дефинират друг идентификатор на единица. Например двата класа

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 и CcuStErrDefinition трябва да имат UnitId, който е зададен в извлечения BaseClass?

Сега, след като дефинирах моите три статусни класа, искам да ги вкарам в регистър. В момента използвам този код, за да се опитам да ги получа. Проблемът е, че резултатът няма елементи.

  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. Факт е, че тези членове са членове на инстанция. Има ли начин да извадя стойностите от тях?


person Daniel W.    schedule 07.08.2013    source източник
comment
x.BaseType ще ви даде незабавното наследяване, а не родителя на родителя, както можете да прочетете тук - msdn.microsoft.com/en-us/library/system.type.basetype.aspx   -  person No Idea For Name    schedule 07.08.2013


Отговори (1)


Първо нещо: вашата 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"),
person lordkain    schedule 07.08.2013
comment
Съжалявам, бях малко зает! Да, това ми помогна много и работи както трябва! Благодаря ти! - person Daniel W.; 07.08.2013