2015-06-02 7 views
5

क्योंकि मॉड्यूल के आदेश का समाधान किया जा रहा इसकी गारंटी नहीं है कि मैं इस को प्राप्त करने के लिए कुछ समस्या आ रही है:Autofac इंतजार उपलब्ध होने के लिए

मैं एक मॉड्यूल जो पंजीकृत करता है एक ScheduleService इस ScheduleService सेट पर ट्रिगर घटनाओं के लिए जिम्मेदार है अंतराल इत्यादि

मैं विभिन्न IScheduable आइटमों में लोड करने में सक्षम हूं जो मैं XML Configuration का उपयोग करके ऐसा करता हूं। मेरे पास समस्या है, IScheduable आइटमों को IScheduleService तैयार होने की आवश्यकता है ताकि यह स्वयं का पंजीकरण कर सके।

तो मेरी <autofac><modules> मैं

<module type="Namespace.ScheduleServiceModule, Namespace" /> 

फिर विचार था मैं के रूप में कई अलग अलग ISchedulable

<module type="SomeNamespace.ScheudleItem1, SomeNamespace /> 
<module type="SomeNamespace.ScheudleItem2, SomeNamespace /> 
<module type="SomeNamespace.ScheudleItem3, SomeNamespace /> 
<module type="SomeNamespace.ScheudleItem4, SomeNamespace /> 

मदों में लोड कर सकता है यह वर्तमान में मैं उन scheduleitem मॉड्यूल में यह करना है:

protected override void Load(ContainerBuilder builder) 
{ 
    builder.RegisterCallback(registry => 
    { 
     var scheduleService = new TypedService(typeof(IScheduleService)); 
     var registrations = registry.RegistrationsFor(scheduleService); 
     if (registrations != null && registrations.Any()) 
     { 
      IComponentRegistration componentRegistration = registrations.First(); 
      componentRegistration.Activated += (sender, args) => 
      { 
       IScheduleService scheduleService = args.Instance as IScheduleService; 
       if (scheduleService != null) 
       { 
        OnScheduleServiceAvailable(args.Context, scheduleService); 
       } 
      }; 
     } 
    }); 
    base.Load(builder); 
} 

यह अनुसूचीइटम में से प्रत्येक में ओवरराइड है

protected override void OnScheduleServiceAvailable(IComponentContext context, 
                IScheduleService scheduleService) 
{ 
    scheduleService.Add(
     new SqlSyncSchedulable(Enabled, IntervalMS, ConnectionString, SqlSelect, 
      context.Resolve<ILoggerService>(), 
      context.Resolve<IPersonService>(), 
      context.Resolve<ILoggingEventService>(), 
      context.Resolve<ITemplateService>(), 
      context.Resolve<ITemplateLoggingEventService>(), 
      context.Resolve<IRuntimeSettingsService>())); 
} 

जो काफी अंतरिम है। ISchedule आइटम को स्वयं पंजीकृत करना चाहिए लेकिन समस्या यह है कि Schedule सेवा उन वस्तुओं के बाद पंजीकृत हो सकती है।

इसे प्राप्त करने का एक तरीका होना चाहिए?

+0

क्या आप अपना प्रश्न संपादित कर सकते हैं और अपना 'ऑनशेड्यूल सेवा उपलब्ध' स्रोत कोड साझा कर सकते हैं? –

+0

ऑनशेड्यूल सेवा के साथ अपडेट किया गया उपलब्ध –

+0

क्या आप इसके बजाय कारखानों ('Func ') पर निर्भरताओं का उपयोग करने में सक्षम नहीं हैं? निर्भरता तब तक उपलब्ध होने की आवश्यकता नहीं है जब तक अनुरोध नहीं किया जाता है। [प्रतिनिधि कारखानों] देखें [http://docs.autofac.org/en/latest/advanced/delegate-factories.html) – wimh

उत्तर

0

मुझे लगता है कि आपकी समस्या मॉड्यूल के लोड ऑर्डर में नहीं है, बल्कि इसके बजाय निर्भरता डिज़ाइन के बारे में है।

आपको अपने मॉड्यूल और अपनी निर्भरताओं को इस तरह से डिजाइन करना चाहिए कि वे अस्थायी रूप से युग्मित नहीं हैं।

कई संभावित डिज़ाइनों में से एक में शेड्यूल सेवा को संभावित निर्भरताओं की एक सूची की आवश्यकता होती है।

इस डिजाइन में, एक ISchedule की responsibilitt एक schedulable आपरेशन के मापदंडों को परिभाषित करने में है, तो आप Autofac Adapter पैटर्न का उपयोग एक ISyncSchedulable आपरेशन में प्रत्येक अनुसूची रैप करने के लिए, और ScheduleService उन्हें प्रारंभ में जोड़ने के लिए एक List<ISyncSchedulable> की आवश्यकता है ।

एक उदाहरण के रूप (अपने उदाहरण का अनुसरण करते हैं, लेकिन शब्दशः नहीं: मैं एक पूर्ण समाधान देने की तुलना में एक बिंदु बनाने के लिए अधिक कोशिश कर रहा हूँ):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using Autofac; 
using NUnit.Framework; 

namespace Example 
{ 
    public interface ISchedule 
    { 
     bool Enabled { get; } 
     long IntervalMs { get; } 
     string ConnectionString { get; } 
     string SqlSelect { get; } 
    } 

    public class Schedule : ISchedule 
    { 
     public bool Enabled 
     { 
      get { return true; } 
     } 

     public long IntervalMs 
     { 
      get { return 100000; } 
     } 

     public string ConnectionString 
     { 
      get { return "localhost;blabla"; } 
     } 

     public string SqlSelect 
     { 
      get { return "select 1 as A"; } 
     } 
    } 


    // let's assume SqlSyncSchedulable inherits from a common 
    // ISyncSchedulable interface 
    public interface ISyncSchedulable 
    { 
     void RunSchedule(ScheduleService scheduleService); 
    } 

    public class SqlSyncSchedulable : ISyncSchedulable 
    { 
     public ISchedule Schedule { get; private set; } 
     public OtherService OtherService { get; private set; } 

     public SqlSyncSchedulable(ISchedule schedule, 
      OtherService otherService 
      /*,ILoggerService loggerService 
      IPersonService personService, */ 
     ) 
     { 
      Schedule = schedule; 
      OtherService = otherService; 
      // read interval and other data from schedule, 
      // store service references as usual. 
     } 

     public void RunSchedule(ScheduleService scheduleService) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public class OtherService 
    { 

    } 

    public class ScheduleService 
    { 
     public ScheduleService(IList<ISyncSchedulable> schedulables, OtherService otherService /*, ... other dependencies */) 
     { 
      // there is no ADD! Autofac gives you a list of all possible 
      // ISyncSchedulable components 
      SyncSchedulables = schedulables; 
      // ... other dependencies 
     } 

     public IList<ISyncSchedulable> SyncSchedulables { get; set; } 

     // this code is not a proper implementation, nor a scheduler, 
     // it's just a placeholder 
     public void RunSchedules() 
     { 
      foreach (var schedule in SyncSchedulables) 
      { 
       // do your operations, involving ... 
       schedule.RunSchedule(this); 
      } 
     } 
    } 


    public class TestModule : Module 
    { 
     protected override void Load(ContainerBuilder builder) 
     { 
      base.Load(builder); 

      builder.RegisterType<ScheduleService>().AsSelf(); 
      builder.RegisterType<OtherService>().AsSelf(); 

      // don't worry about which type should be registered, 
      // and register each type inheriting from ISchedule 
      // coming from the current assembly 
      // You can even use a single registration for all the 
      // possible implementations of ISchedule, using techniques 
      // explained in http://docs.autofac.org/en/latest/register/scanning.html 
      builder.RegisterAssemblyTypes(GetType().Assembly) 
       .Where(t => t.GetInterfaces().Contains(typeof(ISchedule))) 
       .AsImplementedInterfaces() 
       .InstancePerDependency(); 

      // This registration is a partial, because 
      // SqlSyncChedulable requires a single parameter 
      // of type ISchedule 
      builder.RegisterType<SqlSyncSchedulable>() 
       .AsImplementedInterfaces(); 

      // for each ISchedule class, we register automatically 
      // a corresponding ISyncSchedulable, which 
      builder.RegisterAdapter<ISchedule, ISyncSchedulable>(RegisterISyncSchedulableForEachISchedule) 
       .InstancePerDependency(); 
     } 

     private ISyncSchedulable RegisterISyncSchedulableForEachISchedule(IComponentContext context, ISchedule schedule) 
     { 
      // the parameter of type ISchedule is the corresponding schedule 
      var scheduleParam = new TypedParameter(typeof(ISchedule), schedule); 
      // all the other params are resolved automatically by Autofac. 
      return context.Resolve<ISyncSchedulable>(scheduleParam); 
     } 
    } 

    [TestFixture] 
    public class AutofacTest 
    { 
     [Test] 
     public void TestServiceResolution() 
     { 
      var builder = new ContainerBuilder(); 
      builder.RegisterModule(new TestModule()); 
      var container = builder.Build(); 

      var service = container.Resolve<ScheduleService>(); 

      Assert.That(service.SyncSchedulables[0].GetType(), Is.EqualTo(typeof(SqlSyncSchedulable))); 
     } 

    } 
} 

कृपया ध्यान दें कि मॉड्यूल संकल्प आदेश अब पूरी तरह से decoupled है रनटाइम रिज़ॉल्यूशन के साथ।

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