2011-12-17 51 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

我們處理這個問題的方式是我們所有的業務類都從一個公共基類繼承而來。

公共基類包含一個值setter和一個值getter,它使用反射來設置和獲取類中的屬性。如果請求的屬性不存在,並且調用者指出可以這樣做,則setter將該值添加到用戶定義的字段(UDF)集合中,該集合與您的屬性類似。

這種方法消除了調用者需要知道值的實際存儲方式(即它是類中的常規屬性還是UDF集合中的任何內容),甚至不知道它是什麼數據類型。

例如,呼叫方代碼:

productX.Attributes[Price].SetValueFromString("95,3€"); 
在我們的系統

是:

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

我們利用這個廣泛的數據庫交互,表單數據綁定等

這裏是核心setter方法的一個例子:

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

我留下了一些:

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方法,我們得到的值作爲一個字符串我們使用內部方法調用將值強制轉換爲適當的格式(ValueFromDB,ValueForSQL),這樣您就可以看到它們是如何使用的,但它們非常直接的實現。

0

從DynamicObject繼承什麼?擴展TrySetMember可以讓你這麼做:

dynamic productX = GetProduct(); 
productX.Price = "95,3€"; 
相關問題