2014-08-27 18 views
2

我有一個數據庫結構(實體框架模型),它看起來就像這樣:C#如何用方法中的可選參數解決這個困境?

Business <-1----*-> Users <-*----0..1-> Role

非常簡單明瞭: 企業可以擁有用戶。 用戶必須屬於企業。用戶可能會或可能不會涉及角色。 一個角色可以涉及到很多用戶。

服務器的API級別

我想實現的功能,將允許下面的方法服務:

//get all users 
List<User> GetUsers(); 

//get all users belong to a business 
List<User> GetUsers(int businessId); 

//get all users with specific role 
List<User> GetUsers(int roleId); 

//get all users belong to a business with specific role 
List<User> GetUsers(int businessId, int roleId); 

但我不希望寫4個重載到想什麼,我寫在短短的可選參數/命名的參數,所以 而是那些4的一個方法,我想創建以下服務方法:

List<Users> GetUsers(
    int?? businessId=undefined, int?? roleId=undefined) 
{ 
    var queryResult = new List<users>(); 

    if(!businessId.IsUndefined) 
    queryResult= {get from db all business according to Id.} 

    if(!roleId.IsUndefined) 
    queryResult = queryResult.Where(item=>user.role.Id==roleId) 
} 

現在你想知道與什麼是「??」 thingy ..

好吧,讓我們假設我想獲得所有與角色有關係的用戶。 - 這將返回一個特定的標準。

現在,讓我們假設我想要獲得所有用戶而不考慮角色關係。 - 這將返回一個不同的標準。

但命名的參數只能是可空,以支持該行爲:

List<Users> GetUsers(int? RoleId=null) 
{ 
// is this null becuase it was not specified or is it null because 
// it was called with null as argument. 
// I need to know the difference to give the correct criteria. 
// But I cannot tell the difference from within here... 
// as in here it is simply null or some value. 
} 

所以在這裏談到的解決方案,我想一個int是不只是空, 我也希望它是不可捉摸..和我可以設置一個方法如下:

List<Users> GetUsers(int?? RoleId=undefined) 

所以一個int ??將會是這些例子中的任何一個:

int ?? x =未定義;

int ?? x = null;

int ?? x = 5;

問題是 - 這是可能的嗎? 我可以創建一些允許「int ??」的東西嗎?定義...

如果是這樣 - 我該怎麼做? 如果沒有 - 如何克服這個問題?

+0

'可爲空'有值(非空值)或沒有值(空)。沒有第三種狀態可以使用。您必須創建自己的'Nullable'版本,將其稱爲'NullableOrUndefined'並使用而不是'Nullable '。或者,您可以使用負數來表示'未定義',但前提是您沒有具有負值的有效'RoleId'。 – MarcinJuraszek 2014-08-27 23:30:04

+0

@MarcinJuraszek是的,我在那個方向,但我怎麼告訴C#那個int?這意味着什麼?我沒有發現任何'可空'的含義,告訴'?'表示可以爲空。 – 2014-08-27 23:31:47

+0

它是C#的一部分,你不能使它與你自己的類型一起工作。 'int?'只是'Nullable '的語法糖,並且在C#規範中進行了描述。 – MarcinJuraszek 2014-08-27 23:32:47

回答

3

也許你可以使用「業務」和「角色」包裝類,但定義隱式類型轉換。這些類型轉換將允許您的API用戶向您發送一個intRole.Undefined,或者然後爲空。

因此,例如角色類會是這個樣子:

public class Role 
{ 
    private bool _isUndefined; 
    private int _val; 

    private Role() 
    { 
     _isUndefined = true; 
    } 

    private Role(int val) 
    { 
     _val = val; 
    } 

    public static Role Undefined 
    { 
     get { return new Role(); } 
    } 

    public static implicit operator Role(int val) 
    { 
     return new Role(val); 
    } 
} 

然後你的簽名是這樣的:

List<User> GetUsers(Business business = null, Role role = null); 

和您的用戶可以把它想:

GetUsers(Business.Undefined, Role.Undefined); 

GetUsers(1, 2); 

或者

GetUsers(role: 8); 
0

的問題非常深入的調查和仔細考慮接受的答案後, 我決定去的代碼架構,我認爲現在是最好的之一。

我仍然想保留McGarnagle的答案作爲我的問題的接受答案,因爲它是一個原始問題本身的答案 - 但我不會推薦它作爲我所描述的問題的解決方案,由於實體框架模型和服務方法。

我推薦使用它,但是如果有人在不同的情況下需要代碼undefined,我建議考慮McGarnagle的實現來實現它。

internal class Program 
{ 

    private static void Main(string[] args) 
    { 
     GetUsers(); //get users - all of them - from all businesses - disregard any constrain. 
     GetUsers(1);   //get users - which belong to business 1, not matter which role. 
     GetUsers(1, null); //get users - which belong to business 1 and have no assinged role. 
     GetUsers(roleId: 3); //get users - from all business which relate to role 3. 
     GetUsers(null, null); //syntax error - business cannot be null! (the big benefit) 
     GetUsers(1, 3);  //get users - which belong to business 1 and relate to role 3. 
    } 

    public static List<User> GetUsers(
        int businessId = int.MinValue, int? roleId = int.MinValue) 
    { 
     //int.MinValue - to be considered as undefined. 
     //this is the only way to keep consistency with the model abstraction. 

     //can make a chain query here. 
     //q1 = select according to business or just bring from all businesses. 

     //q2 = q1. Select according to roleId.. 

     //and so on if more parameters involved.. 

     //return final query result. 
    } 

} 
相關問題