Question

I have the following setup: A console application, and a services project with a range of services.

I am trying to use Windsor Castle to install specific services in the application, depending on their namespace in the application.

I have got the following to work fine in my application:

Container.Install(Castle.Windsor.Installer.Configuration.FromXmlFile("components.config"));

However, I have trouble getting the "register all service with specific namespace to work".

In a web application I have made previously, I got the following code to work. However, it seems that when I use Container.Register in my console application, I cannot resolve the services later on.

Code I've previously used in a web application:

// All services in service DLL
            var assembly = Assembly.LoadFrom(Server.MapPath("~/bin/LetterAmazer.Business.Services.dll"));
            ;
            Container.Register(
                Classes.FromAssembly(assembly)
                    .InNamespace("LetterAmazer.Business.Services.Services")
                    .WithServiceAllInterfaces());

            Container.Register(
                Classes.FromAssembly(assembly)
                    .InNamespace("LetterAmazer.Business.Services.Services.FulfillmentJobs")
                    .WithServiceAllInterfaces());

            Container.Register(
                Classes.FromAssembly(assembly)
                    .InNamespace("LetterAmazer.Business.Services.Services.PaymentMethods.Implementations")
                    .WithServiceAllInterfaces());



            // All factories in service DLL
            Container.Register(
                Classes.FromAssembly(assembly)
                    .InNamespace("LetterAmazer.Business.Services.Factory")
                    .WithServiceAllInterfaces());


            Container.Register(Component.For<LetterAmazerEntities>());

When I use the Container.Register code in my console application, I cannot do the following:

orderService = ServiceFactory.Get<IOrderService>();
                fulfillmentService = ServiceFactory.Get<IFulfillmentService>();

As I get a "service could not be resolved".

The code is run in a BackgroundService class, with the following code:

public void Start()
        {
            logger.Info("Starting Background Service...");
            Container.Install(Castle.Windsor.Installer.Configuration.FromXmlFile("components.config"));

            ISchedulerFactory scheduleFactory = new StdSchedulerFactory();
            scheduler = scheduleFactory.GetScheduler();
            scheduler.Start();

            ThreadStart threadStart = new System.Threading.ThreadStart(ScheduleJobs);
            new Thread(threadStart).Start();

            logger.Info("DONE!");
        }

So to sum it all up: how do register all services / classes with a specific namespace, in an external DLL, in a console application?

EDIT:

ServiceFactory.cs:

public class ServiceFactory
    {
        private static ServiceFactory instance = new ServiceFactory();
        private IWindsorContainer container = new WindsorContainer();

        private ServiceFactory()
        {

        }

        /// <summary>
        /// Gets the container.
        /// </summary>
        /// <value>The container.</value>
        public static IWindsorContainer Container
        {
            get { return instance.container; }
        }

        /// <summary>
        /// Gets this instance.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T Get<T>()
        {
            return instance.container.Resolve<T>();
        }

        /// <summary>
        /// Gets all this instance.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IList<T> GetAll<T>()
        {
            return instance.container.ResolveAll<T>();
        }

        /// <summary>
        /// Gets the specified name.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public static T Get<T>(string name)
        {
            return (T)instance.container.Resolve<T>(name);
        }

        /// <summary>
        /// Gets all the specified name.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public static IList<T> GetAll<T>(string name)
        {
            return instance.container.ResolveAll<T>(name);
        }
    }

EDIT-2

If I try to make a resolve in the BackgroundService, after registering the services to my container, I get a:

An unhandled exception of type 'Castle.MicroKernel.ComponentNotFoundException' occurred in Castle.Windsor.dll

Additional information: No component for supporting the service LetterAmazer.Business.Services.Domain.Orders.IOrderService was found

However, I can see that in debug, the IOrderService exists in the "All services" in my container.

EDIT-3

 public interface IOrderService
    {
        Order Create(Order order);

        Order Update(Order order);
        void UpdateByLetters(IEnumerable<Letter> letters);

        List<Order> GetOrderBySpecification(OrderSpecification specification);
        Order GetOrderById(int orderId);
        Order GetOrderById(Guid orderId);

        void Delete(Order order);

        List<OrderLine> GetOrderLinesBySpecification(OrderLineSpecification specification);

        void ReplenishOrderLines(Order order);
    }

EDIT-4: Order service

Note: some of the implementation has been cut

public class OrderService : IOrderService
    {
        private IOrderFactory orderFactory;

        private LetterAmazerEntities repository;
        private ILetterService letterService;
        private ICustomerService customerService;

        public OrderService(LetterAmazerEntities repository,
            ILetterService letterService,
            IOrderFactory orderFactory, ICustomerService customerService)
        {
            this.repository = repository;
            this.letterService = letterService;
            this.orderFactory = orderFactory;
            this.customerService = customerService;
        }

        public Order Create(Order order)
        {
            DbOrders dborder = new DbOrders();

            foreach (var orderLine in order.OrderLines)
            {
                var dbOrderLine = setOrderline(orderLine);
                dborder.DbOrderlines.Add(dbOrderLine);
            }


            dborder.Guid = Guid.NewGuid();
            dborder.OrderCode = GenerateOrderCode();
            dborder.OrderStatus = (int)OrderStatus.Created;
            dborder.DateCreated = DateTime.Now;
            dborder.DateUpdated = DateTime.Now;
            dborder.PaymentMethod = "";
            dborder.CustomerId = order.Customer != null ? order.Customer.Id : 0;

            Price price = new Price();
            price.PriceExVat = order.CostFromLines();
            price.VatPercentage = order.Customer.VatPercentage();
            order.Price = price;

            dborder.Total = order.Price.Total;
            dborder.VatPercentage = order.Price.VatPercentage;
            dborder.PriceExVat = order.Price.PriceExVat;

            repository.DbOrders.Add(dborder);

            repository.SaveChanges();

            return GetOrderById(dborder.Id);
        }

        public Order GetOrderById(Guid orderId)
        {
            DbOrders dborder = repository.DbOrders.FirstOrDefault(c => c.Guid == orderId);
            if (dborder == null)
            {
                throw new ItemNotFoundException("Order");
            }

            var lines = repository.DbOrderlines.Where(c => c.OrderId == dborder.Id).ToList();
            var order = orderFactory.Create(dborder, lines);

            return order;
        }

        public Order GetOrderById(int orderId)
        {
            DbOrders dborder = repository.DbOrders.FirstOrDefault(c => c.Id == orderId);
            if (dborder == null)
            {
                throw new ItemNotFoundException("Order");
            }

            var lines = repository.DbOrderlines.Where(c => c.OrderId == orderId).ToList();
            var order = orderFactory.Create(dborder, lines);

            return order;
        }

        public void Delete(Order order)
        {
            var dborder = repository.DbOrders.FirstOrDefault(c => c.Id == order.Id);
            repository.DbOrders.Remove(dborder);
            repository.SaveChanges();

        }
        public void DeleteOrder(Order order)
        {
            var dborder = repository.DbOrders.FirstOrDefault(c => c.Id == order.Id);

            repository.DbOrders.Remove(dborder);
            repository.SaveChanges();
        }




        #endregion


    }
Was it helpful?

Solution

I think you can do the same thing in a console application too. You just have to create the assembly instance. Considering that the assembly is in the same folder, this should work:

Assembly assembly = Assembly.LoadFrom("MyAssembly.dll");

Container.Register(
    Classes.FromAssembly(assembly)
           .InNamespace("MyNamespace")
           .WithServiceAllInterfaces());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top