Как изменить конфиги в Spring.Net
Преимущество контейнера IoC заключается в том, что вы можете поменяться имитационной службой в нижней части графа объектов. Однако в Spring.Net это сделать гораздо сложнее, чем в других контейнерах IoC. Вот некоторый код, который делает это в Unity и имеет код 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());
}
}
}
Для удобства Spring в файле App.config должно быть указано следующее. Понятно, что это только первый весенний тест, а не второй. Можете ли вы поместить несколько конфигураций пружин в файл конфигурации? Если да, то каков синтаксис и как вы к ним обращаетесь? Или есть другой способ сделать это?
<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>
ОбновитьВот частичный ответ на основе кода вссылки, которые Марко Лахма дал на блог Марка Поллака, У меня есть вышеупомянутые тесты, проходящие со следующим кодом:
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());
}
Это поднимает мне несколько вопросов:
Я хочу интегрировать эту технику в существующий код, который использует обычный контейнер. Почему я должен использовать другой тип контейнера,GenericApplicationContext
в этом случае? Что если я захочу прочитать данные в этот объект из существующего весеннего конфига в app.config или web.config? Будет ли это работать в обычном контексте? Могу ли я тогда написать данные для этих регистраций с кодом?
Как я могу указать этоISomeService
должен быть создан как синглтон? Я имею в виду не предоставление экземпляра синглтона в контейнер, а контейнер для создания экземпляра, разрешения его конструктора и использования его при необходимости этого типа.
как я могу сделать эквивалентcontainer.RegisterType<ISomeService, ServiceImplementationA>();
? Я хочу зарегистрировать сопоставления типов для использования во всех случаях, когда этот тип нужен конструктору.
Что именно делаетcontainer.RegisterType<ServiceImplementationA>("service");
делать? Похоже на регистрациюServiceImplementationA
как реализацияISomeService
ноISomeService
никогда не упоминается, поэтому может быть двусмысленность. например что, еслиServiceImplementationA
реализовано более одного интерфейса.
Зачем нужно имя строки для регистрации? Он не будет работать с пустой строкой, но это не имеет значения, что это такое.
Пытаюсь ли я использовать пружину так, чтобы она просто не работала? Я пытаюсь использовать его как другие контейнеры IoC, но он не совсем работает.