如何在Spring.Net中更改配置 [英] How to change configs in Spring.Net

查看:70
本文介绍了如何在Spring.Net中更改配置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

IoC容器的一个优点是您可以在对象图底部的模拟服务中进行交换.但是,在Spring.Net中,这似乎比在其他IoC容器中要难得多.这是一些在Unity中完成并具有Spring.Net代码的代码;

An advantage of an IoC container is that you can swap in a mock service at the bottom of your object graph. However this seems much harder to do in Spring.Net than in other IoC Containers. Here's some code that does it in Unity and has Spring.Net code;

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文件中包含以下内容.显然,这仅用于第一次弹簧测试,而不能用于第二次弹簧测试.可以在配置文件中放入多个spring配置吗?如果是这样,语法是什么?如何访问它们?还是有另一种方法可以做到这一点?

For the benefit of Spring, the following needed to be in the App.config file. Clearly this only serves the first spring test, and not the second. Can you put multiple spring configurations in the config file? If so, what is the syntax and how do you access them? Or is there another way to do this?

  <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>


更新

这是根据


Update

Here is a partial answer based at code at the links that Marko Lahma gave to Mark Pollack's blog. I have the above tests passing, with the following code:

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());
    }

这向我提出了一些问题:

This raises a few questions to me:

  • 我想将此技术集成到使用常规容器的现有代码中.为什么在这种情况下我必须使用其他容器类型GenericApplicationContext?如果我想从app.config或web.config中现有的spring config中读取数据到该对象中怎么办?它能像往常一样工作吗?然后,我可以使用代码在这些注册中写入数据吗?

  • I want to integrate this technique into existing code that uses the usual container. Why do I have to use a different container type, GenericApplicationContext in this case? What if I want to read data into this object from the existing spring config in app.config or web.config? Would it work as the usual context? Could I then write data over these registrations with code?

如何指定将ISomeService创建为单例?我并不是说要向容器提供单例实例,而是要用容器来创建实例,解析其构造函数并在需要该类型时使用它.

How can I specify that ISomeService is to be created as a singleton? I don't mean supply a singleton instance to the container, but the container to create the instance, resolving its constructor, and use it when that type is needed.

我该怎么做container.RegisterType<ISomeService, ServiceImplementationA>();的等价物?我想注册类型映射,以在构造函数需要该类型的所有情况下使用.

how can I do the equivalent of container.RegisterType<ISomeService, ServiceImplementationA>(); ? I want to register type mappings to use in all cases where that type is needed by a constructor.

container.RegisterType<ServiceImplementationA>("service");的确切作用是什么?似乎将ServiceImplementationA注册为ISomeService的实现,但从未提及ISomeService,因此可能存在歧义.例如如果ServiceImplementationA实现了多个接口怎么办?

What exactly does container.RegisterType<ServiceImplementationA>("service"); do? It seems to register ServiceImplementationA as the implementation of ISomeService but ISomeServiceis never mentioned, so there could be ambiguity. e.g. what if ServiceImplementationA implemented more than one interface.

为注册指定的字符串名称是什么?它不能与空字符串一起使用,但这似乎无关紧要.

What is the string name given to the registration for? It won't work with en empty string, but it doesn't seem to matter what it is.

我是否试图以某种无法使用spring的方式使用spring?我正在尝试像其他IoC容器一样使用它,但效果不佳.

Am I trying to use spring in a way that it just does not work? I'm trying to use it like other IoC containers, but it's not quite working.

推荐答案

添加为尝试解决开放点的新答案...

Adding as new answer trying to address the open points...

我想整合这项技术 到使用常规代码的现有代码中 容器.为什么我必须使用 不同的容器类型 GenericApplicationContext在此 案子?如果我想将数据读入该怎么办 来自现有弹簧的这个物体 在app.config或web.config中配置? 它能像往常一样工作吗? 然后我可以在这些上写数据吗 用代码注册吗?

I want to integrate this technique into existing code that uses the usual container. Why do I have to use a different container type, GenericApplicationContext in this case? What if I want to read data into this object from the existing spring config in app.config or web.config? Would it work as the usual context? Could I then write data over these registrations with code?

Spring针对不同类型的初始化策略提供了具体的应用程序上下文实现.最常用的是GenericApplicationContext(手动),XmlApplicationContext(XML文件)和WebApplicationContext(非常类似于XmlApplicationContext,但是为Web使用量身定制的).它们都实现公共接口:IApplicationContext,这是访问这些容器的首选方法.

Spring has concrete application context implementations for different kind of initialization tactics. The most common ones to use are GenericApplicationContext (manual), XmlApplicationContext (XML files) and WebApplicationContext (very much like XmlApplicationContext but tailored for web use). They all implement common interface: IApplicationContext which is the preferred way to access these containers.

用代码无意更改注册通常意味着您需要直接使用特定的子类.对于GenericApplicationContext和StaticApplicationContext,这是很自然的事情,但是XmlApplicationContext通常被认为仅是XML,因此可以固定"到XML定义.

Unfortonately altering registrations with code usually means that you need to use the specific sub-class directly. With GenericApplicationContext and StaticApplicationContext this is quite natural but XmlApplicationContext is usually considered to be XML only and this ways "fixed" to XML definition.

如何指定ISomeService为 被创建为一个单身人士?我不 意味着向提供一个单例实例 容器,但容器 创建实例,解决其实例 构造函数,并在该类型时使用它 是必需的.

How can I specify that ISomeService is to be created as a singleton? I don't mean supply a singleton instance to the container, but the container to create the instance, resolving its constructor, and use it when that type is needed.

您的SpringHelper就是这样做的,默认情况下,Spring中的所有对象都是单例.您可以通过使用false调用ObjectDefinitionBuilder的SetSingleton方法来更改此行为.

Your SpringHelper does just that, by default all objects in Spring are singletons. You could alter this behavior by calling ObjectDefinitionBuilder's SetSingleton method with false.

我该怎么做 container.RegisterType(); ?我想要 注册类型映射以用于所有 在这种情况下 构造函数.

how can I do the equivalent of container.RegisterType(); ? I want to register type mappings to use in all cases where that type is needed by a constructor.

Spring使用对象名称(id)来区分不同的实现.因此,如果有多种选择,如果您希望获得用于特定实例的特定类型,则应按名称引用该特定实例.如果您正在使用自动装配,并且您的对象具有接口ISomeService的依赖关系,并且只有一个实现该对象的对象注册,则自动装配可以毫无歧义地对其进行设置.

Spring uses object names (ids) to distinct between different implementations. So if you want to get specific type to serve a specific instance in case that there are many alternatives you should refer to this specific instance by name. If you are using autowiring and your object has dependency to interface ISomeService and there's only one object registered that implements it, the autowiring can set it without ambiguity.

究竟是什么 container.RegisterType("service"); 做?好像在登记 ServiceImplementationA作为 ISomeService的实现,但是 从未提及ISomeService,因此 可能会有歧义.例如如果什么 ServiceImplementationA已实施 一个以上的界面.

What exactly does container.RegisterType("service"); do? It seems to register ServiceImplementationA as the implementation of ISomeService but ISomeServiceis never mentioned, so there could be ambiguity. e.g. what if ServiceImplementationA implemented more than one interface.

从上一个答案继续,此注册名为"service"的ServiceImplementationA类型的单例.该对象带有自动实现的候选对象及其所有实现的接口(当然还有其具体类型).

Continuing from previous answer, this registers singleton of type ServiceImplementationA with name "service". This object comes autowiring candidate with all it's implemented interfaces (and with it's concrete type of course).

给该字符串的字符串名称是什么 注册吗?它不能与 zh_cn空字符串,但似乎没有 不管是什么.

What is the string name given to the registration for? It won't work with en empty string, but it doesn't seem to matter what it is.

这非常重要,如前所述.该名称在该上下文中是唯一的ID(父上下文可能具有相同名称的对象),并且可用于访问特定的对象注册.简而言之,在其他框架可能将类型关联为对象注册的键的情况下,Spring使用名称.

It matters a great deal as explained earlier. The name is unique id within that context (parent context could have object with same name) and can be used to access specific object registrations. In short where other frameworks may associate a type as key to object registration, Spring uses name.

这篇关于如何在Spring.Net中更改配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆