Castle Windsor Typed Factory Странности

Я получаю очень неожиданное (я думаю) поведение с помощью средства Typed Factory. По сути, это повторное использование экземпляров временных компонентов для внедрения конструктора с помощью Func<T>.

Вот суть:

// this guy is registered as service EntityFrameworkRepositoryProvider, not IRepository
[Transient] 
public class EntityFrameworkRepositoryProvider : IRepository 
{
    public EntityFrameworkRepositoryProvider(ObjectContext objectContext, Assembly assembly)
    {
         // HOLY MOLY BATMAN!! Every time I hit this constructor when getProvider gets called,
         // I don't actually get the arguments passed into getProvider. I get the 
         // arguments that were passed into getProvider the very FIRST time 
         // it was called...in other words I get the wrong 
         // ObjectContext (for the wrong connection string)...BIG PROBLEM


         // do stuff...
    }
}

[Singleton]
// this guy gets registered on startup
internal class EntityFrameworkRepositoryProviderFactory : IRepositoryProviderFactory
{
      private readonly Func<ObjectContext, Assembly, EntityFrameworkRepositoryProvider> getProvider;

      public EntityFrameworkRepositoryProviderFactory(Func<ObjectContext, Assembly, EntityFrameworkRepositoryProvider> getProvider) 
      {
          this.getProvider = getProvider;
          // do stuff...
      }

      public IRepository CreateRepository()
      {
          var provider = getProvider(new ObjectContext(GetConnectionString()),
              Assembly.GetExecutingAssembly);
          // do stuff...
      }

      public string GetConnectionString() 
      { 
             // returns one of a few diff EF connection strings
      }          
}

У меня также есть стандартный LazyComponentLoader. Что я здесь делаю неправильно? Что мне делать вместо этого?

Спасибо.


person Jeff    schedule 17.12.2010    source источник


Ответы (1)


Проблема заключалась в этом, казалось бы, безобидном коде в LazyComponentLoader:

        public IRegistration Load(string key, Type service, IDictionary arguments)
        {
            var component = Component.For(service);

            if (!string.IsNullOrEmtpy(key))
            {
                component = component.Named(key);
            }

            if (arguments != null)
            {
                // This makes the typed factory facility screw up. (Merge is an extension method that merges dictionaries)
                component.DynamicParameters((k, d) => d.Merge(arguments));
            }                

            return component;
        }

   public static void Merge(this IDictionary target, IDictionary source)
    {
        foreach (object key in source.Keys)
        {
            target[key] = source[key];
        }
    }
person Jeff    schedule 17.12.2010
comment
зависит от того, как вы реализуете свой метод Merge. Если вы просто добавите свои собственные аргументы к d, все будет в порядке. Если вы по-прежнему считаете, что поведение каким-то образом ошибочно или не соответствует вашим ожиданиям, не стесняйтесь поднимать этот вопрос для обсуждения в группе пользователей Castle в группах Google. - person Krzysztof Kozmic; 18.12.2010
comment
Хорошая точка зрения! Проблема в том, что Merge перезаписывает, я думаю... поэтому первый набор параметров, который я Merge(), в конечном итоге перезаписывает второй (см. Impl выше). - person Jeff; 18.12.2010
comment
... так что, возможно, поведение ожидаемо (не ошибочно). - person Jeff; 18.12.2010