2011-10-31 12 views
5

के साथ एक सामान्य इंटरफ़ेस सजा रहा है मेरे पास एक सामान्य इंटरफ़ेस है, जो दो सामान्य प्रकारों में होता है। मैं वापस लौटाए गए सभी संस्करणों को सजाना चाहता हूं, लेकिन जब से मैं एनरिकविथ को कॉल करते समय इस प्रकार को नहीं जानता, तो यह स्पष्ट रूप से संकलित नहीं होता है। मैंने एनरिकविथ ओवरलोड का उपयोग करने का प्रयास किया है जो संदर्भ में गुजरता है, सोच रहा है कि मैं जेनेरिक प्रकारों को पारित कर सकता हूं और एक्टिवेटर को कॉल कर सकता हूं। क्रिएटइंस्टेंस, लेकिन इस पर संदर्भ में कोई उपयोगी जानकारी नहीं है जब इसे डिबगिंग और निरीक्षण किया जाता है।स्ट्रक्चरमैप

यहां तक ​​कि मेरे पास अब तक है।

public class SignUpService : IServiceOperation<SignUpRequest, SignUpResult> 
{ 
    private readonly IUserRepository _userRepo; 

    public SignUpService(IUserRepository userRepo) 
    { 
     _userRepo = userRepo; 
    } 

    public SignUpResult PerformService(SignUpRequest validatedRequest) 
    { 
     var user = Mapper.Map<User>(validatedRequest); 

     user.MarkAsLoggedIn(); 
     user.ChangePassword(validatedRequest.UnhashedPassword); 

     using(var transaction = _userRepo.BeginTransaction()) 
     { 
      _userRepo.Save(user); 
      transaction.Commit(); 
     } 

     return new SignUpResult(); 
    } 
} 

यहाँ मेरी डेकोरेटर है, कि अन्य सेवा के लिए ले जाता है के रूप में अच्छी तरह से:

public interface IServiceOperation<in TRequest, out TResponse> where TResponse : ServiceResult, new() 
{ 
    TResponse PerformService(TRequest validatedRequest); 
} 

यहां नमूने के कार्यान्वयन है: यह मेरा सामान्य इंटरफेस है

public class ValidateServiceDecorator<TRequest, TResponse> : IServiceOperation<TRequest, TResponse> where TResponse : ServiceResult, new() 
{ 
    private readonly IServiceOperation<TRequest, TResponse> _serviceOperation; 
    private readonly IValidationService _validationService; 

    public ValidateServiceDecorator(IServiceOperation<TRequest, TResponse> serviceOperation, 
     IValidationService validationService) 
    { 
     _serviceOperation = serviceOperation; 
     _validationService = validationService; 
    } 

    public TResponse PerformService(TRequest request) 
    { 
     var response = new TResponse(); 
     var validationResult = _validationService.Validate(request); 

     if (!validationResult.IsValid) 
     { 
      response.ValidationErrors = validationResult.ValidationErrors; 
      return response; 
     } 

     return _serviceOperation.PerformService(request); 
    } 

अन्त में, यहाँ कैसे है अब तक मैं अपने कंटेनर पर मिल गया है। यह स्पष्ट रूप से संकलित नहीं है, लेकिन EnrichWith लाइन मैं क्या हासिल करने की कोशिश कर रहा हूँ पता चलता है:

public class StructureMapServiceScanner : Registry 
{ 
    public StructureMapServiceScanner() 
    { 
     Scan(scanner => 
       { 
        scanner.AssemblyContainingType(typeof (IServiceOperation<,>)); 
        scanner.ConnectImplementationsToTypesClosing(typeof (IServiceOperation<,>)); 
       }); 

     For(typeof (IServiceOperation<,>)) 
     .EnrichWith((ioc, original) => new ValidateServiceDecorator(original, ioc.GetInstance<IValidationService>())); 
    } 
} 

और सिर्फ इसलिए कि इस सवाल का थोड़ा और कोड की जरूरत है, यहाँ अपने परीक्षण है कि मैं पारित करने के लिए प्राप्त करने के लिए कोशिश कर रहा हूँ है :

[TestClass] 
public class StructureMapServiceScannerSpecs 
{ 
    [TestMethod] 
    public void Test() 
    { 
     ObjectFactory.Configure(cfg => 
            { 
             cfg.AddRegistry<StructureMapServiceScanner>(); 
             cfg.For<IUserRepository>().Use(new Mock<IUserRepository>().Object); 
             cfg.For<IValidationService>().Use(new Mock<IValidationService>().Object); 
            }); 

     var service = ObjectFactory.GetInstance<IServiceOperation<SignUpRequest, SignUpResult>>(); 

     service.ShouldNotBeNull(); 
     service.ShouldBeType<ValidateServiceDecorator<SignUpRequest, SignUpResult>>(); 
    } 
} 

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

+0

प्रत्येक बंद प्रकार के इंटरफेस को सीधे समृद्ध करने के लिए पंजीकरण कॉन्फ़्रेंस का उपयोग करके इसे समझने में सक्षम था। मैं जो पोस्ट करता हूं वह पोस्ट करता हूं, लेकिन मैं कुछ और घंटों तक नहीं कर सकता। – Robert

उत्तर

4

अंततः इसे समझने में सक्षम था।

public class ServiceRegistrationConvention : IRegistrationConvention 
{ 
    public void Process(Type type, Registry registry) 
    { 
     var interfacesImplemented = type.GetInterfaces(); 

     foreach (var interfaceImplemented in interfacesImplemented) 
     { 
      if (interfaceImplemented.IsGenericType && interfaceImplemented.GetGenericTypeDefinition() == typeof(IServiceOperation<,>)) 
      { 
       var genericParameters = interfaceImplemented.GetGenericArguments(); 
       var closedValidatorType = typeof(ValidateServiceDecorator<,>).MakeGenericType(genericParameters); 

       registry.For(interfaceImplemented) 
        .EnrichWith((context, original) => Activator.CreateInstance(closedValidatorType, original, 
                       context.GetInstance<IValidationService>())); 
      } 
     } 
    } 
} 
3

यहाँ एक दृष्टिकोण है कि अभी भी StructureMap के आईओसी क्षमताओं का लाभ उठाता है, की अनुमति के अतिरिक्त सेवाओं अपने डेकोरेटर में आसानी से इंजेक्ट किया जा रहा है: मैं एक RegistrationConvention बनाया। यह सही नहीं है क्योंकि यह मानता है कि आप प्राथमिक कंटेनर का उपयोग कर रहे हैं न कि एक बच्चे के कंटेनर, लेकिन यह शायद अधिकांश परिदृश्यों के लिए काम करेगा।

public class ServiceRegistrationConvention : IRegistrationConvention 
{ 
    public void Process(Type type, Registry registry) 
    { 
     var handlerInterfaces = (from t in type.GetInterfaces() 
           where t.IsGenericType && 
             t.GetGenericTypeDefinition() == typeof (IHandle<,>) 
           select t); 

     foreach (var handler in handlerInterfaces) 
     { 
      var decoratorType = typeof (ValidationDecorator<,>).MakeGenericType(handler.GetGenericArguments()); 

      registry.For(handler) 
       .EnrichWith((ctx, orig) => ObjectFactory.With(handler, orig).GetInstance(decoratorType)); 
     } 
    } 
} 

आदर्श रूप में, StructureMap के iConText विधि के साथ बेनकाब करना चाहिए जैसे IContainer करता है। इसके बिना, इस समस्या का वास्तव में एक अच्छा समाधान नहीं है।

संबंधित मुद्दे

 संबंधित मुद्दे