2017-09-29 58 views
3

我想找到一種方法來完善我有的一些代碼。我與第三方API一起工作,該API有一個非常複雜的API請求對象(我將其稱爲ScrewyAPIObject),其中有大量的重複。每次你想設置一個特定的屬性,它可能需要一頁代碼。所以我建立了一個庫來爲其屬性的設置/獲取提供一個簡化的包裝(並處理一些值預處理)。尋找一種更優雅的方式來執行類屬性上的自定義獲取/設置功能

這裏是它是如何工作的精簡視圖:

public abstract class LessScrewyWrapper 
{ 
    protected ScrewyAPIRequest _screwy = new ScrewyAPIRequest(); 

    public void Set(string value) 
    { 
     Set(_getPropertyName(), value); 
    } 

    public void Set(string property, string value) 
    { 
     // Preprocess value and set the appropriate property on _screwy. This part 
     // has tons of code, but we'll just say it looks like this: 
     _screwy.Fields[property] = "[" + value + "]"; 
    } 

    protected string _getPropertyName() 
    { 
     // This method looks at the Environment.StackTrace, finds the correct set_ or 
     // get_ method call and extracts the property name and returns it. 
    } 

    public string Get() 
    { 
     // Get the property name being access 
     string property = _getPropertyName(); 

     // Search _screwy's structure for the value and return it. Again, tons of code, 
     // so let's just say it looks like this: 
     return _screwy.Fields[property]; 
    } 

    public ScrewyAPIRequest GetRequest() 
    { 
     return _screwy; 
    } 
} 

然後,我有一個代表一種特定類型的扭曲API請求的子類(有多種類型,所有具有相同的結構,但不同的設置)。遠的不說這其中有兩個字符串屬性,PropertyA和PropertyB:

public class SpecificScrewyAPIRequest : LessScrewyWrapper 
{ 
    public string PropertyA 
    { 
    get { return Get(); } 
    set { Set(value); } 
    } 
    public string PropertyB 
    { 
    get { return Get(); } 
    set { Set(value); } 
    } 
} 

現在,當我想要去使用這個庫,我可以這樣做:

SpecificScrewyAPIRequest foo = new SpecificScrewyAPIRequest(); 
foo.PropertyA = "Hello"; 
foo.PropertyB = "World"; 
ScrewyAPIRequest request = foo.GetRequest(); 

這工作好得很,但有不同類型的數據類型,這涉及到在我的Set/Get方法中使用泛型,當你處理50個屬性和Get()和Set()調用的50個副本時,它只是讓子類看上去有點笨拙。

我想要做的就是簡單地定義的字段,如:

public class SpecificScrewyAPIRequest : LessScrewyWrapper 
{ 
    public string PropertyA; 
    public string PropertyB; 
} 

這將使類看起來更清潔。問題是,我不知道有什麼方法讓.NET在我的自定義處理程序對域的值進行訪問和修改時進行回調。我已經看到有人在PHP中使用__set和__get魔術方法來做類似這樣的事情(儘管它們並不打算被使用),但是在C#中我沒有發現任何類似的東西。有任何想法嗎?

編輯:我已經考慮使用索引方法來處理我的類的對象類型的值,之後將其轉換爲適當的類型,但我更願意保留使用特定類型定義屬性的方法。

+2

如果你的代碼工作正常,你可以發佈到[代碼審查]你的問題(https://codereview.stackexchange.com/) –

+1

你在做什麼只是夫妻您通過添加一個層永遠扭曲最佳。我建議儘可能脫鉤。使用POCO作爲您的邏輯,然後在API調用之前有一個將POCO轉換爲Screwy的函數,反之亦然。你在做什麼就像實現JSON.NET,通過反射性更新每次設置屬性時基礎的JSON編碼的字符串。它永遠將你的邏輯與編碼相結合,效率低下,難以理解。 –

+0

這就是技術上的轉換功能,所以它是有意耦合的。所有的業務邏輯等已經被分解爲POCO,然後應用程序接受POCO,然後使用該庫將最終結果轉換爲API請求。 – jhilgeman

回答

1

也許在你的情況DynamicObject是一個合適的選擇:

public class ScrewyDynamicWrapper : DynamicObject 
{ 
    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     // get your actual value based on the property name 

     Console.WriteLine("Get Property: {0}", binder.Name); 
     result = null; 
     return true; 
    } 

    public override bool TrySetMember(SetMemberBinder binder, object value) 
    { 
     // set your actual value based on the property name 

     Console.WriteLine("Set Property: {0} # Value: {2}", binder.Name, value); 
     return true; 
    } 
} 

,並定義包裝對象:

public class ScrewyWrapper 
{ 
    protected dynamic ActualWrapper = new ScrewyDynamicWrapper(); 

    public int? PropertyA 
    { 
     get { return ActualWrapper.PropertyA; } 
     set { ActualWrapper.PropertyA = value; } 
    } 

    public string PropertyB 
    { 
     get { return ActualWrapper.PropertyB; } 
     set { ActualWrapper.PropertyB = value; } 
    } 
} 

但是,你不能依靠屬性類型裏面ScrewyDynamicWrapper這種方法,所以這取決於你的實際API要求 - 也許它不適合你。

1

而不是字段,如果您在類中定義爲屬性,它會更容易。

public class SpecificScrewyAPIRequest 
{ 
    public string PropertyA { get; set; } 
    public string PropertyB { get; set; } 
} 

然後您可以創建擴展通用方法來返回ScrewyAPIRequest對象。

public static class Extensions 
{ 
    public static ScrewyAPIRequest GetRequest<T>(this T obj) 
    { 
     ScrewyAPIRequest _screwy = new ScrewyAPIRequest(); 

     var test= obj.GetType().GetProperties(); 
     foreach (var prop in obj.GetType().GetProperties()) 
     { 
      _screwy.Fields[prop.Name] = prop.GetValue(obj, null); 
     } 
     return _screwy; 
    } 
} 

現在你可以很容易地從任何類對象獲得ScrewyAPIRequest

您的代碼如下所示。

 SpecificScrewyAPIRequest foo = new SpecificScrewyAPIRequest(); 
     foo.PropertyA = "Hello"; 
     foo.PropertyB = "World"; 
     ScrewyAPIRequest request = foo.GetRequest(); 
相關問題