we_will_rise Δημοσ. 17 Μαρτίου 2015 Δημοσ. 17 Μαρτίου 2015 Χαίρεται. Έχω μια Service στην οποία έχω εφτακόσιες τριανταδώδεκα μεθόδους αυτού του στυλ [WebMethod] public ResponseMessage LogIn(string Username, string Password, bool Persist) { ResponseMessage result = new ResponseMessage(); try { // do shit } catch (Exception ex) { result = new ResponseMessage(ex); } finally { /* do shit */ } return result; } H κλάσση Response Message είναι αυτή [System.Web.Script.Services.ScriptService] public class ResponseMessage { public bool Succeeded { get; set; } public object Data { get; set; } public string Message { get; set; } public ResponseMessage() { Succeeded = true; Data = null; Message = string.Empty; } public ResponseMessage(Exception ex) { Succeeded = false; Data = null; Message = ex.Message; } } όλες οι εφτακόσιες τριανταδώδεκα μέθοδοι είναι πανομοιότυπες και το μόνο που αλλάζει είναι αυτό που γίνεται μέσα στο try και αυτό μέσα στο finally. Υπάρχει κάνενας τρόπος να γράφω ΜΟΝΟ το περιεχόμενο της try και της finally και τα υπόλοιπα να τα "καλώ";; Τίποτα με delegates ξερω γω;
albNik Δημοσ. 17 Μαρτίου 2015 Δημοσ. 17 Μαρτίου 2015 Δοκιμασε αυτο delegate void TryHandler(); delegate void FinallyHandler(); ResponseMessage LogIn(string Username, string Password, bool Persist) { return Helper(() => { /* do shit */ }, () => { /* do shit */}); } ResponseMessage Helper(TryHandler tryAction, FinallyHandler finallyAction) { ResponseMessage result = new ResponseMessage(); try { if(tryAction != null) tryAction(); } catch(Exception ex) { result = new ResponseMessage(ex); } finally { if(finallyAction != null) finallyAction(); } return result; } 1
we_will_rise Δημοσ. 17 Μαρτίου 2015 Μέλος Δημοσ. 17 Μαρτίου 2015 Δοκιμασε αυτο delegate void TryHandler(); delegate void FinallyHandler(); ResponseMessage LogIn(string Username, string Password, bool Persist) { return Helper(() => { /* do shit */ }, () => { /* do shit */}); } ResponseMessage Helper(TryHandler tryAction, FinallyHandler finallyAction) { ResponseMessage result = new ResponseMessage(); try { if(tryAction != null) tryAction(); } catch(Exception ex) { result = new ResponseMessage(ex); } finally { if(finallyAction != null) finallyAction(); } return result; } Είσαι άρχοντας
Papakaliati Δημοσ. 17 Μαρτίου 2015 Δημοσ. 17 Μαρτίου 2015 Χωρις να εχει μεγαλη διαφορα, το delegate void TryHandler(); δεν χρειαζεται και μπορεις να γραψεις κατευθειαν ResponseMessage Helper(System.Action tryAction, System.Action finallyAction){ ... } Και μπορεις να στειλεις σαν Action method, δηλαδη ResponseMessage LogIn(string Username, string Password, bool Persist) { return Helper( method1, method2);} private void method1 (){ ... } private void method2 (){... } ResponseMessage Helper(System.Action tryAction, System.Action finallyAction) { ResponseMessage result = new ResponseMessage(); try { if(tryAction != null) tryAction(); } catch(Exception ex) { result = new ResponseMessage(ex); } finally { if(finallyAction != null) finallyAction(); } return result;} 1
albNik Δημοσ. 17 Μαρτίου 2015 Δημοσ. 17 Μαρτίου 2015 Παντως εχει σημασια στις try και finally ποιες μεταβλητές καλούνται (πχ παραμετροι UserName/Password ή τοπικές ResponseMessage result). Δεν ειναι παντα ευκολος ο χωρισμός σε 2 actions
AllCowsEatGrass Δημοσ. 17 Μαρτίου 2015 Δημοσ. 17 Μαρτίου 2015 Νομίζω πως μπορεί να γίνει καλύτερο! Ίσως θα μπορούσες να έχεις ένα Interface με όλα τα methods του Service σου και δύο classakia που το κάνουν implement. Το ένα θα έχει όλη τη λογική που θέλεις (Α) και το άλλο (Β) θα κρατάει εσωτερικά ένα ref του Α για να κάνει delegate τα calls. Το Β θα είναι responsible για το "safe calling" των Service methods, εκεί (στο Β) ίσως θελήσεις να βάλεις extra safe calliing λογική στο μέλλον (retry, logging, trace).Just an idea!
defacer Δημοσ. 17 Μαρτίου 2015 Δημοσ. 17 Μαρτίου 2015 Γενικά θα προτιμούσα τη νοοτροπία του papakaliati γιατί καλές χρυσές οι lambdas αλλά you can have too much of a good thing. Αν το /* do shit */ υπάρχει περίπτωση να είναι παραπάνω από απλό expression τότε καλύτερα να έχεις τα πράγματα ωραιά και ξεχωριστά. Όπως είπε ο albNik μπορεί να χρειαστεί να αναφερθείς σε μεταβλητές από το περιβάλλον (π.χ. username, password) αλλά αυτό δεν είναι πρόβλημα γιατί θα τις κάνεις capture αυτόματα αν τις χρησιμοποιήσεις στη lambda. Σε περίπτωση που χρειαστεί να αναφερθείς σε κάποια μεταβλητή και μέσα από το work action και μέσα από το cleanup action: προσωπικά το θεωρώ καμπανάκι κακού design και θα σταματούσα επιτόπου για να εφαρμόσω άλλη λύση. Μια δεύτερη προσέγγιση που μπορείς να δοκιμάσεις να δεις αν σου αρέσει είναι εκμεταλλευόμενος το using/IDisposable: sealed class CleanerUpper : IDisposable { private readonly Action cleanupAction; public CleanerUpper(Action cleanupAction) { this.cleanupAction = cleanupAction; } public void Dispose() { this.cleanupAction(); } } [WebMethod] public blah blah { using (new CleanerUpper(() => Console.WriteLine("Clean up"))) { Console.WriteLine("Do work"); throw new Exception("foo"); } } Και τέλος, αν θέλεις να αυτοματοποιήσεις κάποιες διαδικασίες σε "βιομηχανικό" επίπεδο, ίσως αξίζει να δεις και τη λύση των T4 templates: βασικά γράφεις σε C# ένα πρόγραμμα το οποίο παράγει source code τον οποίο κάνεις compile τελικά μέσα στο project σου. Για παράδειγμα ένα T4 template θα μπορούσε να κάνει reflection σε μια class και να σου φτιάξει αυτόματα (την ώρα του compile) ένα WebService με Ν WebMethods οι οποίες τελικά θα εξυπηρετούνται από την εν λόγω class.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα