2011-12-17 8 views
1

私はウェブサイトから解析された値を商品に記入しようとしています。プロセスはうまくいく。私が欲しいのは、簡単に(カップリングを減らして)製品の値を簡単に埋めることです。 現時点では、値を追加する方法はproductX.Attributes[Price].SetValueFromString("95,3€");です。下記のデザインを見て、改善してください。この解析メカニズムで使用するデザインパターンはどれですか?

class Product 
{ 
    Dictionary<KeyValuePair<Type, AAtribute>> _attributes; 

    Product() 
    { 
     // add values to _attributes. for example 
     // Name with StrinAttribute 
     // Price with NumericAttribute 
     // Images with StringListAttribute 
    } 
} 

enum Type 
{ 
    Name, 
    Price, 
    Images 
    ... 
} 

abtract class AAtribute 
{ 
    abstract void SetValueFromString(string value); 
} 

とAAtributeから派生するいくつかのクラスがあります。

  • StringAtributeは、
  • StringListAtribute
  • KeyValueStringListAtribute
  • BoolAtribute
  • NumericAtribute

私はこのデザインを作っているので、他のクラスでは魔法の属性がどのような型か、値を与える方法を知る必要はありません。 例えば、私は価格属性に値を与えたい場合は私が言う:

productX.Attributes[Price].SetValueFromString("95,3€"); 

を40個の以上の属性があるので、これは本当に役立っています。手作業でそれぞれの価値を解析するのは苦痛です。

私の問題は、カップリングをさらに減らすことはできません。他のクラスにAAtributesや製品タイプを知らないようにするためのアイデアはありますか?デコレータと戦略パターンの間に何かがあるべきですが、私はそれに道を見つけることができません。

- ListStringAttributeに値を追加するにはどうすればよいですか?

しかし、これは問題を引き起こし、リファクタリングが必要だと感じていることを知っています。

答えて

1

これを処理する方法は、すべてのビジネスクラスが共通の基本クラスを継承することです。

共通基本クラスには、クラス内でプロパティを設定および取得するためにリフレクションを使用する値セッターと値ゲッターが含まれています。要求されたプロパティーが存在せず、呼び出し元がそれを行うことがOKであることが示された場合、セッターはその値をユーザー定義フィールド(UDF)コレクションに追加します。

このアプローチでは、値が実際にどのように格納されているか(つまり、クラスまたはUDFコレクションの通常のプロパティ)、またはそれがどのデータ型であるかについての呼び出し側の必要性が取り除かれます。例えば

、あなたの発信者コード:私たちのシステムで

productX.Attributes[Price].SetValueFromString("95,3€"); 

は次のようになります。

productX.SetFieldValue("Price", "95,3€"); 

私たちは、データベースとの対話のために広くこれを使用、フォームデータ等、結合しますここで

は、コアセッターメソッドの例です。

public static void SetFieldValue(object oRecord, string sName, object oValue) 
    { 
     PropertyInfo theProperty = null; 
     FieldInfo theField = null; 
     System.Type oType = null; 

     try 
     { 
      oType = oRecord.GetType(); 

      // See if the column is a property in the record 
      theProperty = oType.GetProperty(sName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public, null, null, new Type[0], null); 
      if (theProperty == null) 
      { 
       theField = oType.GetField(sName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public); 
       if (theField != null) 
       { 
        theField.SetValue(oRecord, Global.ValueFromDB(oValue, theField.FieldType.Name)); 
       } 
       else 
       { 
        object[] aAttributes = null; 

        // See if the class type is decorated with the NoUDFs attribute. If so, do not add the attribute. 
        aAttributes = oType.GetCustomAttributes(typeof(NoUDFsAttribute), true); 
        if (aAttributes.Length == 0) 
        { 
         // Otherwise, anything that is not found as a property or a field will be stored as a UDF 
         oRecord.SetUDFValue(sName, oValue); 
        } 
       } 
      } 
      else 
      { 
       if (theProperty.CanWrite) 
       { 
        theProperty.SetValue(oRecord, Global.ValueFromDB(oValue, theProperty.PropertyType.Name), null); 
       } 
      } 
     } 
     catch (Exception theException) 
     { 
      // Handle the exception 
     } 
    } 

そして、我々は文字列として値を取得するgetterメソッドの1:

public static string GetFieldValueForSQL(object oRecord, string sName) 
    { 
     PropertyInfo theProperty = null; 
     FieldInfo theField = null; 
     System.Type oType = null; 

     try 
     { 
      oType = oRecord.GetType(); 

      // See if the column is a property in the record 
      theProperty = oType.GetProperty(sName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public, null, null, new Type[0], null); 
      if (theProperty == null) 
      { 
       theField = oType.GetField(sName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public); 
       if (theField != null) 
       { 
        return Global.ValueForSQL(theField.GetValue(oRecord), theField.FieldType.Name); 
       } 
       else 
       { 
        UDF oUDF = null; 
        object[] aAttributes = null; 

        // See if the class type is decorated with the NoUDFs attribute. If so, do not get the value. 
        aAttributes = oType.GetCustomAttributes(typeof(NoUDFsAttribute), true); 
        if (aAttributes.Length == 0) 
        { 
         oUDF = oRecord.GetUDF(sName); 
        } 

        if (oUDF != null) 
        { 
         return Global.ValueForSQL(oUDF.Value); 
        } 
        else 
        { 
         return "Null"; 
        } 
       } 
      } 
      else 
      { 
       return Global.ValueForSQL(theProperty.GetValue(oRecord, null), theProperty.PropertyType.Name); 
      } 
     } 
     catch (Exception theException) 
     { 
      // Handle the exception 
      return null; 
     } 
    } 

私はのいくつかを残してきました値を適切な形式(ValueFromDB、ValueForSQL)に強制的に変換して使用方法を確認できる内部メソッド呼び出しですが、実装するのはかなり簡単です。

0

DynamicObjectから継承することはどうですか? TrySetMemberを延長すると、これを行うことができます:

dynamic productX = GetProduct(); 
productX.Price = "95,3€"; 
関連する問題