Jak zmienić configs w Spring.Net

Zaletą kontenera IoC jest to, że można zamienić próbną usługę na dole wykresu obiektu. Jednak wydaje się to znacznie trudniejsze w Spring.Net niż w innych kontenerach IoC. Oto kod, który robi to w Unity i ma kod Spring.Net;

namespace IocSpringDemo
{
    using Microsoft.Practices.Unity;
    using NUnit.Framework;

    using Spring.Context;
    using Spring.Context.Support;

    public interface ISomeService
    {
        string DoSomething();
    }

    public class ServiceImplementationA : ISomeService
    {
        public string DoSomething()
        {
            return "Hello A";
        }
    }

    public class ServiceImplementationB : ISomeService
    {
        public string DoSomething()
        {
            return "Hello B";
        }
    }

    public class RootObject
    {
        public ISomeService SomeService { get; private set; }

        public RootObject(ISomeService service)
        {
            SomeService = service;
        }
    }

    [TestFixture]
    public class UnityAndSpringDemo
    {
        [Test]
        public void UnityResolveA()
        {
            UnityContainer container = new UnityContainer();
            container.RegisterType<ISomeService, ServiceImplementationA>();
            RootObject rootObject = container.Resolve<RootObject>();
            Assert.AreEqual("Hello A", rootObject.SomeService.DoSomething());
        }

        [Test]
        public void UnityResolveB()
        {
            UnityContainer container = new UnityContainer();
            container.RegisterType<ISomeService, ServiceImplementationB>();
            RootObject rootObject = container.Resolve<RootObject>();
            Assert.AreEqual("Hello B", rootObject.SomeService.DoSomething());
        }

        [Test]
        public void SpringResolveA()
        {
            IApplicationContext container = ContextRegistry.GetContext();
            RootObject rootObject = (RootObject)container.GetObject("RootObject");
            Assert.AreEqual("Hello A", rootObject.SomeService.DoSomething());
        }

        [Test]
        public void SpringResolveB()
        {
            // does not work - what to do to make this pass?
            IApplicationContext container = ContextRegistry.GetContext();
            RootObject rootObject = (RootObject)container.GetObject("RootObject");
            Assert.AreEqual("Hello B", rootObject.SomeService.DoSomething());
        }
    }
}

Dla dobra Springa następujące pliki musiały znajdować się w pliku App.config. Najwyraźniej służy to tylko pierwszemu testowi wiosennemu, a nie drugiemu. Czy możesz umieścić wiele konfiguracji sprężyn w pliku konfiguracyjnym? Jeśli tak, jaka jest składnia i jak do nich uzyskać dostęp? Czy może jest to inny sposób?

  <configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
    </sectionGroup>
  </configSections>
  <spring>
    <context>
      <resource uri="config://spring/objects"/>
    </context>
    <objects xmlns="http://www.springframework.net">
      <object name="RootObject" type="IocSpringDemo.RootObject, IocDemo" autowire="constructor" />
      <object name="service" type="IocSpringDemo.ServiceImplementationA, IocDemo" autowire="constructor" />
    </objects>
  </spring>
Aktualizacja

Oto częściowa odpowiedź oparta na kodzie wlinki, które Marko Lahma przekazał blogowi Marka Pollacka. Mam powyższe testy z następującym kodem:

public static class SpringHelper
{
    public static T Resolve<T>(this IApplicationContext context, string name)
    {
        return (T)context.GetObject(name);
    }

    public static void RegisterType<T>(this GenericApplicationContext context, string name)
    {
        context.RegisterType(name, typeof(T));
    }

    public static void RegisterType(this GenericApplicationContext context, string name, Type type)
    {
        IObjectDefinitionFactory objectDefinitionFactory = new DefaultObjectDefinitionFactory();
        ObjectDefinitionBuilder builder = ObjectDefinitionBuilder.RootObjectDefinition(objectDefinitionFactory, type);
        builder.SetAutowireMode(AutoWiringMode.AutoDetect);

        context.RegisterObjectDefinition(name, builder.ObjectDefinition);
    }
}

...

    [Test]
    public void SpringResolveA()
    {
        GenericApplicationContext container = new GenericApplicationContext();
        container.RegisterType<RootObject>("RootObject");
        container.RegisterType<ServiceImplementationA>("service");

        RootObject rootObject = container.Resolve<RootObject>("RootObject");
        Assert.AreEqual("Hello A", rootObject.SomeService.DoSomething());
    }

    [Test]
    public void SpringResolveB()
    {
        GenericApplicationContext container = new GenericApplicationContext();
        container.RegisterType<RootObject>("RootObject");
        container.RegisterType<ServiceImplementationB>("service");

        RootObject rootObject = container.Resolve<RootObject>("RootObject");
        Assert.AreEqual("Hello B", rootObject.SomeService.DoSomething());
    }

To rodzi dla mnie kilka pytań:

Chcę zintegrować tę technikę z istniejącym kodem, który używa zwykłego kontenera. Dlaczego muszę używać innego typu kontenera,GenericApplicationContext w tym przypadku? Co zrobić, jeśli chcę odczytać dane do tego obiektu z istniejącej konfiguracji spring w app.config lub web.config? Czy będzie to działać jak zwykły kontekst? Czy mógłbym następnie zapisać dane dotyczące tych rejestracji za pomocą kodu?

Jak mogę to określićISomeService ma być stworzony jako singleton? Nie mam na myśli dostarczania pojedynczego instancji do kontenera, ale kontenera, aby utworzyć instancję, rozwiązać jej konstruktor i użyć go, gdy ten typ jest potrzebny.

jak mogę zrobić odpowiednikcontainer.RegisterType<ISomeService, ServiceImplementationA>(); ? Chcę zarejestrować odwzorowania typów do użycia we wszystkich przypadkach, w których ten typ jest potrzebny konstruktorowi.

Co dokładnie robicontainer.RegisterType<ServiceImplementationA>("service"); robić? Wydaje się, że się rejestrujeServiceImplementationA jak wdrożenieISomeService aleISomeServicenigdy nie jest wymieniany, więc może istnieć dwuznaczność. na przykład co jeśliServiceImplementationA zaimplementowano więcej niż jeden interfejs.

Jaka jest nazwa łańcucha przypisana do rejestracji? Nie będzie działać z pustym łańcuchem en, ale nie ma znaczenia, co to jest.

Czy próbuję użyć sprężyny w sposób, który po prostu nie działa? Próbuję go używać jak innych kontenerów IoC, ale to nie działa.

questionAnswers(2)

yourAnswerToTheQuestion