Reputation: 9966
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
}
Upvotes: 2
Views: 1974
Reputation: 38468
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());
Upvotes: 1