1

次のような 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 を定義する 2 つ以上の他の基本クラスがあります。たとえば、2 つのクラス

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 の 3 つのクラスには、派生した BaseClass に設定されている UnitId が必要ですか?

3 つのステータス クラスを定義したので、それらをレジストリに入れたいと思います。現在、このコードを使用してそれらを取得しようとしています。問題は、結果にアイテムがないことです。

  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 になることです。実際には、これらのメンバーはインスタンス メンバーです。それらから値を取得する方法はありますか?

4

1 に答える 1

2

まず最初に: 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"),
于 2013-08-07T06:17:37.030 に答える