JonasGao
JonasGao

Reputation: 255

Can i inject component without interface use windsor

I like ioc. Earlier, i use Spring in Java, now, i want use DI in C#. I found castle.windsor. But it does not seem to direct injection class.

Now, I try this, but fail.... Someone, can you help me fix it? Or, tell me, What DI framework can i use?

Program.cs

using System;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;

namespace InjectionConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            var container = new WindsorContainer();
            container.Install(new MainInstaller());

            var service1 = container.Resolve<Service1>();

            service1.Say();

            // clean up, application exits
            container.Dispose();

            Console.ReadKey();
        }
    }

    class MainInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Classes.FromThisAssembly());
        }
    }
}

Service1.cs

using System;

namespace InjectionConsole
{
    class Service1
    {
        private Service2 Service2 { get; set; }

        public void Say()
        {
            Console.WriteLine("Hello, I m Service 1, let me call Service 2");

            Service2.Say();
        }
    }
}

Service2.cs

using System;

namespace InjectionConsole
{
    class Service2
    {
        public void Say()
        {
            Console.WriteLine("Hello, I m Service 2");
        }
    }
}

Upvotes: 0

Views: 866

Answers (3)

Gertjan
Gertjan

Reputation: 41

It seems that you didn't mark the Service1 and Service2 classes as public, which will make them internal by default. The Classes.FromThisAssembly() method loads public types only, unless you explicitly tell it to load nonpublic types as well (which is discouraged by the way!). Check the docs on the castle windsor GitHub docs page.

Upvotes: 1

Scott Hannen
Scott Hannen

Reputation: 29222

My answer is similar to another but with one hair-splitting difference:

public class Service1
{
    private readonly Service2 _service2;

    public Service1(Service2 service2) {
        _service2 = service2;
    }

    public void Say()
    {
        Console.WriteLine("Hello, I m Service 1, let me call Service 2");

        _service2.Say();
    }
}

First, the class itself would be written exactly the same way whether or not you're using a container like Windsor. The class has to "get" its dependency (an instance of Service2) from somewhere. So we put it in the constructor. Service1 expects whatever creates it to supply a Service2. Since you're using the container, the container creates Service1, it sees in the constructor that it needs a Service2, and it supplies that.

Making _service2 a readonly field emphasizes that once it's created (the constructor is done executing) Service1 has no further control over the value of _service2. It's set and cannot be changed, not even within Service1. That's important because we don't want Service1 to control that dependency. We want it to require that dependency. It just takes whatever value is passed in and uses it.

Again, that's a hair-splitting difference. If you don't make _service2 readonly you probably wouldn't change it anyway. But this makes clear that you can't change it.

Upvotes: 0

George Chen
George Chen

Reputation: 6939

I assume you wanna resolve Service2 in your Service1 instance. You can achieve that by constructor injection

using System;

namespace InjectionConsole
{
    class Service1
    {
        public Service1(Service2 s2) {
            this.Service2 = s2;
        }

        private Service2 Service2 { get; set; }

        public void Say()
        {
            Console.WriteLine("Hello, I m Service 1, let me call Service 2");

            Service2.Say();
        }
    }
}

Upvotes: 1

Related Questions