Pergunta

I have a base class called BaseStatus which looks like this:

 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;
        }
}

Furthermore i have two or more other base classes which derive from BaseStatus and define a other unit id. For example the two classes

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;
        }
    }

The Background is that i want to derive from for example BaseCcuStatus and have the correct UnitId in the derived class.

Now i define my correct status classes for example:

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;
        }
    }

For my understading, the three classes StatStErrDefinition, GcmStErrDefinition and CcuStErrDefinition should have the UnitId which is set in the derived BaseClass?

Now that i have defined my three Status Classes i want to get them into a registry. Currently im using this piece of code to try get them. Problem is that the result has no items.

  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;
                    }

After the LINQ expression the var unitStatus is empty...

Later, the registry call looks like that to get the specific class but that is unimportant at this point:

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

For information: I want to get the status class which should be in the registry by the unittypeid and the specific status value. Currently my registry method does not work because he is not able to find any class. So there has to be a mistake somewhere. Thanks in advance

#Update 1

I changed my functionality a little bit:

 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 contains now the correct type. Problem is that if temp is type of StatStErrDefinition the StatusValue and UnitId Property is null. The fact is that these members are instance members. Is there a way to get the values out of them?

Foi útil?

Solução

First thing first : your linq query is pretty long. divide it in different step and store them in differtent variables (or make propertys out of them, whatever you prefer)

This is

  1. easy to read / maintain
  2. easy to debug

With this givin I think you are able to solve youre problem :)

To check if the class is of a certain type you could use teh method .OfType

Use this method to get the value. Notice that you must make an instance in your case because the value change in your constructor.

 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;
 }

Instead of

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

use

UnitId = GetPropValue(x,"UnitId"),
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top