Skip to content
hendryluk edited this page Feb 11, 2015 · 8 revisions

What is a component?

"Component" in Cormo is what they call "bean" in Spring and Java EE lingo. We don't have an equivalent in the .NET vocabulary that conveys the same concept, so instead we'll use an unfortunately overloaded term: component.

Managed Components are defined as container-managed objects with minimal programming restrictions, otherwise known by the acronym POCO (Plain Old .NET Object). They support a small set of basic services, such as resource injection, lifecycle callbacks and interceptors.

With very few exceptions, almost every concrete .NET class that has a constructor with no parameters (or a constructor designated with the attribute [Inject]) is a component. If you’ve already got some POCO classes lying around, they’re already components—you won’t need any additional special metadata.

The POCO classes you’ve been writing every day, up until now, have not been able to take advantage of the new services defined by the CDI specification. But you’ll be able to use every one of them with CDI—allowing the container to create and destroy instances of your components and associate them with a designated context, injecting them into other components, specializing them with qualifier attributes, even adding interceptors and decorators to them—without modifying your existing code. At most, you’ll need to add some attributes.

Now let’s see how to create your first component that actually uses CDI.

1.2. Getting our feet wet

Suppose that we have an existing .NET class that we’ve been using for years.

public class Greeter: IGreeter 
{
   public string Greet(string name) { return "Hello " + name; }
}

public interface IGreeter // <- interface is optional
{
   public string Greet(string name);

}

Without any modification you can now consume this e.g. from a WebApi controller.

[RestController]
public class HelloController
{
   [Inject] IGreeter _greeter;
   
   [Route("hello")]
   public string Hello(string name)
   {
      return _greeter.Greet(name);
   }
}

Notice that it is not necessary to create a controller or property to inject one component to another. Cormo can access an injected field directly (even if it's private), which sometimes helps eliminate some wasteful code. The name of the field is arbitrary. It's the field's type that determines what is injected.

At system initialization time, the container must validate that exactly one component exists which satisfies each injection point. In our example, if no implementation of IGreeter is available — if the dll that contains Greeter class was not deployed — the container would inform us of an unsatisfied dependency. If more than one implementation of IGreeter were available, the container would inform us of the ambiguous dependency.

Alternatively we may obtain an instance of IGreeter programatically from an injected instance of IInstance, parameterized with the component type:

   [Inject] IInstance<IGreeter> _greeter;
   
   [Route("hello"), HttpGet]
   public string Hello(string name)
   {
      return _greeter.Value.Greet(name);
   }

IInstance<IGreeter> also extends IEnumerable<IGreeter>, which allows you to inject multiple instances of IGreeter.

Another way to define your component is by creating a Producer method.

public class GreeterProducer
{
   [Produces] Greeter GetGreeter(MyOtherDependency foo, OtherThing bar)
   {
      return new Greeter("sheep", foo) { Bar = bar };
   }
}

The injection code remains unchanged:

[Inject] IGreeter _greeter;

Before we get too deep in the details, let's pause and examine a component's anatomy. What aspects of the component are significant, and what gives it its identity? Instead of just giving examples of components, we're going to define what makes something a component.

Credit: https://docs.jboss.org/weld/reference/2.1.0.Final/en-US/html/intro.html