2010-10-19 16 views
22

इसी सवाल से पहले कहा गया है करने के लिए पारित करने के लिए वर्तमान उपयोगकर्ता की जानकारी नहीं बल्कि काफी एक ही (जब तक मैं इसे याद किया)कैसे DDD में सभी परतें

मैं अपने सेवा, डोमेन, डोमेन घटनाक्रम के माध्यम से IUserInfo वर्ग उदाहरण पास करना चाहते हैं , डोमेन इवेंट हैंडलर ...

ऐसा करने का सबसे अच्छा तरीका क्या है।

क्या मुझे

  • यह Httpcontext.Current.session [ "CurrentUser"] के कहने के खिलाफ यह पंजीकरण से आईओसी का उपयोग कर सम्मिलित करें;

  • वर्तमान थ्रेड में डेटा जोड़ें।

  • कोई अन्य रास्ता

मैं डोमेन ईवेंट हैंडलर्स पर अटक कर रहा हूँ जहाँ मैं ईमेल भेजने के साथ ही लेखा परीक्षा के लिए डेटा का उपयोग करना चाहते हैं।

मैं अपने आवेदन में लगभग कहीं से भी CurrentUser जानकारी का उपयोग करने में सक्षम होना चाहता हूं।

धागे के रूप में धागे के साथ थ्रेडिंग के साथ मुझे संदेह है यदि धागे का पुन: उपयोग डेटा को रीसेट करेगा। यदि नहीं, तो कृपया मुझे IUser उदाहरण पास करने के लिए थ्रेडिंग का उपयोग कैसे करें।

सादर,

मार्च

+0

मैं सिर्फ यह कहना चाहता था कि मेरे प्रश्न के साथ थोड़ा ओवरलैप है कि मैंने हाल ही में रेस्पोजिटरीज को उपयोगकर्ता संदर्भ के बारे में जागरूक होने की अनुमति देने के बारे में और पूछा है। मैं अन्य उपयोगकर्ता संदर्भ संवेदनशील मानों तक पहुंचने के लिए उपयोगकर्ता संदर्भ का उपयोग करने के मुद्दे के साथ इस समस्या को हल करने का प्रयास कर रहा हूं। http://stackoverflow.com/questions/5374176/can-ddd-repositories-be-aware-of-user-context – jpierson

उत्तर

5

मैं आईओसी उपयोग करने से पहले बात इस तरह का किया है। इसका लाभ यह है कि यह बहुत ही टेस्टेबल है - आप परीक्षण के लिए अपनी उपयोगकर्ता जानकारी को रोक सकते हैं - और उचित रूप से पठनीय और अनुसरण करने में आसान।

+0

धन्यवाद। मैं एक और दिन इंतजार करूँगा यह देखने के लिए कि किसी और के पास अन्य विचार हैं या नहीं। आईओसी तरीके के लिए आप इसे Httpcontext.Current.session ["CurrentUser"] में पहले संग्रहीत कर रहे थे? – TheMar

+1

मैं इसे सत्र में संग्रहीत नहीं करता बल्कि बल्कि HttpContext.Items में संग्रहीत करता हूं। सत्र जारी है लेकिन HttpContext.Items केवल अनुरोध के जीवनकाल के लिए मौजूद है, इसलिए यह इस तरह की चीजों के लिए सही है। – hackerhasid

+5

मैंने शायद कुछ गलत समझा है, लेकिन आप सभी परतों से HttpContext तक कैसे पहुंच सकते हैं, उदाहरण के लिए, डोमेन को HttpContext के बारे में कुछ भी नहीं पता होना चाहिए? – vorou

16

मेरा दृष्टिकोण आदर्श नहीं हो सकता है, लेकिन मुझे लगता है कि यह काफी अच्छी तरह से काम कर रहा है। मैंने जो किया वह मैंने किया - मैंने का उपयोग करने का निर्णय नहीं लिया निर्भरता इंजेक्शन वर्तमान उपयोगकर्ता को हर जगह सीधे पास कर दिया क्योंकि यह बहुत बोझिल हो रहा था और स्थिर संदर्भ में स्विच किया गया था। संदर्भों में समस्या - उन्हें प्रबंधित करना थोड़ा मुश्किल है।

यह एक अपने डोमेन में परिभाषित किया गया है:

public static class UserContext{ 
    private static Func<User> _getCurrentUser; 
    private static bool _initialized; 
    public static User Current{ 
    get{ 
     if(!_initialized) 
     throw new Exception("Can i haz getCurrentUser delegate?"); 
     var user=_getCurrentUser(); 
     return user??User.Anonymous; 
    } 
    } 
    public static void Initialize(Func<User> getCurrentUser){ 
    _getCurrentUser=getCurrentUser; 
    _initialized=true; 
    } 
} 

ध्यान दें कि प्रतिनिधि स्थिर है - पूरे अनुप्रयोग के लिए केवल एक समय में एक। और मैं इसके जीवन चक्र, संभावित मेमोरी लीक या व्हाट्नॉट के बारे में 100% निश्चित नहीं हूं।

क्लाइंट एप्लिकेशन संदर्भ आरंभ करने के लिए ज़िम्मेदार है। मेरे वेब एप्लिकेशन है जो करता है हर अनुरोध पर:

public class UserContextTask:BootstrapperTask{ 
private readonly IUserSession _userSession; 
public UserContextTask(IUserSession userSession){ 
    Guard.AgainstNull(userSession); 
    _userSession=userSession; 
} 
public override TaskContinuation Execute(){ 
    UserContext.Initialize(()=>_userSession.GetCurrentUser()); 
    return TaskContinuation.Continue; 
} 
} 

धारा लाइन बूटस्ट्रैपिंग कार्यों के mvcextensions पुस्तकालय का उपयोग करना। आप इसके लिए global.asax में घटनाओं के अनुसार बस सदस्यता ले सकते हैं।

क्लाइंट साइड (वेब ​​एप्लिकेशन) में, मैं आवेदन सेवा नामित IUserSession लागू:

public User GetCurrentUser(){ 
    if(HttpContext.Current.User==null) return null; 
    var identity=HttpContext.Current.User.Identity; 
    if(!identity.IsAuthenticated) return null; 
    var user=_repository.ByUserName(identity.Name); 
    if(user==null) throw new Exception("User not found. It should be. Looks bad."); 
    return user; 
} 

वहाँ आदेश/ओ सदस्यता प्रदाता और भूमिका प्रदाता w भूमिकाओं के साथ रूपों प्रमाणीकरण का उपयोग करने के लिए कुछ और lame code आवश्यक है। लेकिन यह इस सवाल का मुद्दा नहीं है।

डोमेन स्तर पर - मैं स्पष्ट रूप से अनुमतियाँ उपयोगकर्ताओं इस तरह हो सकता है वर्णन कर रहा हूँ: - उन अनुमतियों और अधिक परिष्कृत किया जा सकता है

public class AcceptApplications:IUserRights{ 
    public bool IsSatisfiedBy(User u){ 
    return u.IsInAnyRole(Role.JTS,Role.Secretary); 
    } 
    public void CheckRightsFor(User u){ 
    if(!IsSatisfiedBy(u)) throw new ApplicationException 
     ("User is not authorized to accept applications."); 
    } 
} 

कूल बात है। उदाहरण के लिए:

public class FillQualityAssessment:IUserRights{ 
    private readonly Application _application; 
    public FillQualityAssessment(Application application){ 
    Guard.AgainstNull(application, 
     "User rights check failed. Application not specified."); 
    _application=application; 
    } 
    public bool IsSatisfiedBy(User u){ 
    return u.IsInRole(Role.Assessor)&&_application.Assessors.Contains(u); 
    } 
    public void CheckRightsFor(User u){ 
    if(!IsSatisfiedBy(u)) 
     throw new ApplicationException 
     ("User is not authorized to fill quality assessment."); 
    } 
    } 

अनुमतियां विपरीत भी vica जाँच की जा सकती - उपयोगकर्ता इन दोस्तों है:

public virtual bool HasRightsTo<T>(T authorizationSpec) where T:IUserRights{ 
    return authorizationSpec.IsSatisfiedBy(this); 
} 
public virtual void CheckRightsFor<T>(T authorizationSpec) where T:IUserRights{ 
    authorizationSpec.CheckRightsFor(this); 
} 

यहाँ मेरी कुल जड़ आधार वर्ग है:

public class Root:Entity,IRoot{ 
    public virtual void Authorize(IUserRights rights){ 
    UserContext.Current.CheckRightsFor(rights); 
    } 
} 

और यहाँ है कि कैसे मैं अनुमतियों की जाँच करें:

public class Application{ 
    public virtual void Accept(){ 
    Authorize(new AcceptApplications()); 
    OpeningStatus=OpeningStatus.Accepted; 
    } 
} 

मुझे उम्मीद है कि मदद करता है ...

+1

@ अर्निस- विस्तृत उदाहरण के लिए धन्यवाद। कोड पर देखकर मैं पठनीयता चिंता के लिए आईओसी मार्ग की ओर झुका हुआ हूं और स्थिर वर्ग को बनाए रखने के बारे में सोचना नहीं है। मैं अभी भी इसे एक कोशिश देने और कार्रवाई में देखने जा रहा हूं। – TheMar

+0

मुझे लगता है कि इसे थोड़ा सा सरल बनाया जा सकता है लेकिन फिर भी HttpContext पर निर्भरता से पीड़ित होगा जिसका अर्थ है कि यह बहुत टेस्टेबल नहीं है। आईओसी का उपयोग करके आप वेबसाइट के लिए एचटीपी कॉनटेक्स्ट का उपयोग कर सकते हैं लेकिन जो भी आप परीक्षण के लिए चाहते हैं उसे पास कर सकते हैं। आईएमओ यह एक बड़ा प्लस है। – hackerhasid

+0

@statichippo मेरे उदाहरण में नियंत्रण में उलटा है। 'प्रारंभिक' समारोह में प्रतिनिधि को पास करना आईओसी है। संदर्भ स्वयं को कुछ भी नहीं जानता है कि यह वर्तमान उपयोगकर्ता कैसे प्राप्त होगा। उपयोगकर्ता अनुप्रयोग कार्यान्वयन वेब अनुप्रयोग में बैठता है, डोमेन तकनीकी चिंताओं से मुक्त है। यह टेस्टेबल है - मुझे बस इसकी आवश्यकता के साथ इसे शुरू करने की आवश्यकता है। केवल बुरी चीज है - यह स्थैतिक है और यदि उपयोगकर्ता कुछ भी उपयोगकर्ता कॉन्टेक्स्ट का उपयोग करेगा तो मैं शीर्ष से नहीं देख सकता। –