Resolve caste windsor failing - castle-windsor

Recently upgraded to version 3.2.1 of castle windsor and receiving an error when attempting to resolve a service that previously didn't occur in version 3.0 of the windsor framework.
IWindsorContainer container = new WindsorContainer();
The following code no longer works
// Throws component not found exception
InstallerHelper.ProcessAssembliesInBinDirectory(
assembly => container.Register(
Classes
.FromAssembly(assembly)
.BasedOn<IWindsorInstaller>()
.WithService.FromInterface()
.LifestyleSingleton()
));
var installers = container.ResolveAll<IWindsorInstaller>();
container.Install(installers);
// Fails here, is it related to a hashcode mismatch in SimpleTypeEqualityComparer?
var credentialCache = container.Resolve<ICredentialCache>()
// works fine if explicity install installers individually
container.Install(new CredentialsInstaller());
var credentialCache = container.Resolve<ICredentialCache>()
Where ProcessAssembliesInBinDir is:
public static void ProcessAssembliesInBinDirectory(Action<Assembly> action)
{
var directoryName = GetDirectoryName();
foreach (var dll in Directory.GetFiles(directoryName, "*.dll"))
{
var fileInfo = new FileInfo(dll);
if (!IgnoreList.Any(x=>fileInfo.Name.StartsWith(x)))
{
var assembly = Assembly.LoadFile(dll);
action(assembly);
}
}
}
Where credential installer is:
public class CredentialsInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ICredentidalCache>()
.ImplementedBy<CredentidalCache>()
.LifestyleSingleton()
);
// This works fine
var credentialCache = container.Resolve<ICredentialCache>()
}
}
Class implementation
public interface ICredentidalCache {}
public class CredentidalCache : ICredentidalCache{}
This is being run from an MVC application
version 4.5 of the .net framework
the credential installer lives inside another assembly, referenced by the website
using the Windsor source, the successful attempt to resolve occurs when the typeof(ICredentialCache).GetHashCode() is the same as what has been registered. For some reason when returning out of the installer the hashcode has changed for the type. Putting a debug line inside SimpleTypeEqualityComparer.GetHashCode(Type obj) shows that hashcodes are different for the same Type.
inspecting the container inside the debugger shows the ICredentialCache successfully installed.
Edit
Manage to move forward by manually registering installers, ie. not relying on the resolve<IwindsorInstaller>() and use container.install(new Installer(), ...). If i find out more I'll update the SO question.

This works fine for me:
public sealed class AppServiceFactory
{
...
public T Create<T>()
{
return (T)container.Resolve(typeof(T));
}
...
}
AppServiceFactory.Instance.Create<IYourService>();

The problem is caused by the InstallerHelper and how it goes about loading an assembly. This SO post pointed me in the right direction,
https://stackoverflow.com/a/6675227/564957
essentially the way the assembly was loaded was failing using Assembly.LoadFile(string fileName) was causing the problem, changing this to be Assembly.Load(string assemblyName) rectified the issue.
#Eric Lippert does a good job explaining
[when] loading an assembly by its path, and one via loading the same
assembly by its assembly name... reflection will
consider types from the two loadings of the same assembly to be
different types. Any assembly loaded from its path is considered to be
distinct from an assembly loaded by its assembly name.

Related

How do I use Castle Windsor to create a RavenDB session with client version > 3.0.3660?

I am using Castle Windsor v3.4.0 to create a RavenDB document session instance but when I use a RavenDB client version later than 3.0.3660 I get this error when calling the Store method:
Castle.MicroKernel.ComponentNotFoundException: 'No component for supporting the service System.Net.Http.HttpMessageHandler was found'
Here is the smallest piece code I can come up with that reproduces the error:
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Raven.Client;
using Raven.Client.Document;
public class Program
{
public static void Main()
{
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component
.For<IDocumentStore>()
.ImplementedBy<DocumentStore>()
.DependsOn(new { Url = "http://localhost:8081", DefaultDatabase = "Test" })
.OnCreate(x => x.Initialize())
.LifeStyle.Singleton,
Component
.For<IDocumentSession>()
.UsingFactoryMethod(x => x.Resolve<IDocumentStore>().OpenSession())
.LifeStyle.Transient);
using (var documentSession = container.Resolve<IDocumentSession>())
{
documentSession.Store(new object());
documentSession.SaveChanges();
}
}
}
Here's what I believe is happening. A change was made to the RavenDB client after v3.0.3660 that changed how the HttpMessageHandler is created in the HttpJsonRequest class:
https://github.com/ravendb/ravendb/commit/740ad10d42d50b1eff0fc89d1a6894fd57578984
I believe that this change in combination with my use of the TypedFactoryFacility in my Windsor container is causing RavenDB to request an instance of HttpJsonRequestFactory and it's dependencies from Windsor rather than using it's own internal one.
How I can change my code to avoid this problem so that I can use a more recent version of the RavenDB client?
Given your MVCE, Windsor is set up to inject object's properties. So, when creating the DocumentStore, Castle is trying to find a value for the HttpMessageHandlerFactory property and is failing since nothing is configured for that particular type.
I was able to get your example to work (at least, it got to inserting the data into my non-existing server) by just filtering out that property:
container.Register(
Component.For<IDocumentStore>()
.ImplementedBy<DocumentStore>()
.DependsOn(new { Url = "http://localhost:8081", DefaultDatabase = "Test" })
.OnCreate(x => x.Initialize())
.PropertiesIgnore(p => p.Name == nameof(DocumentStore.HttpMessageHandlerFactory))
.LifeStyle.Singleton);
Alternatively, if you have a value for it, you could add it to the object passed to DependsOn().

Startup.cs error (ASP.Net Core configuration)

I am trying to set up an ASP.Net Core application to read in configuration settings from a json file. I am using VS2015 and .NetCore 1.0 (with .Net Core Tools preview 2). I am having problems getting a simple piece of boiler plate code to compile.
I am using the following code, which was published at
http://asp.net-hacker.rocks/2016/03/21/configure-aspnetcore.html
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
if (env.IsDevelopment())
{
// This will push telemetry data through Application Insights
// pipeline faster, allowing you to view results immediately.
builder.AddApplicationInsightsSettings(developerMode: true);
}
Configuration = builder.Build();
}
However, the IDE/compiler complains that 'the name "Configuration" does not exist in the current context' (last line of code). The only suggestion from the IDE is to include Microsoft.Extensions.Configuration. However this is a namespace which does not contain an object or property named "Configuration".
In addition 'AddApplicationInsightsSettings' fails with does IConfigurationBuilder not contain a definition for AddApplicationInsightsSettings and no extension method AddApplicationInsightsSettings accepting a first argument of type IConfigurationBuilder could be found
Any suggestions please ?
Thanks
Simply add Configuration property to your Startup class, tutorial has missed this 'step':
public IConfigurationRoot Configuration { get; set; }
ConfigurationBuilder.Build() method just returns instance of IConfigurationRoot, that you should save, if need to get settings further in Startup class (in ConfigureServices method for example).
Regarding second error, looks like you didn't add the Application Insights dependency:
{
"dependencies": {
"Microsoft.ApplicationInsights.AspNetCore": "1.0.0"
}
}

How to only use IOC container from MVVMCross

I'm working on a existing Windows Phone project and want to use the IOC container from MVVMCross, but not the other extra features (yet).
I installed MVVMCross.Core 4.x and try to use 'ConstructAndRegisterSingleton' from the App() constructor of the Windows app, but it throws an Null ref exception.
Tried to find any bootstrapper, setup or initialization for MVVMCross but can't find any in the new 4.x core.
Anyone any idea?
Found it.... and it seems to work.
Just get MVVMCross.Core from Nuget and create a setup like:
internal static class Setup
{
public static void InitializeIoc()
{
CreateIocProvider();
// Register all services
Mvx.ConstructAndRegisterSingleton<ILoudnessLimitsRegulator, LoudnessLimitsRegulator>();
}
private static void CreateIocProvider()
{
// Ioc options
var options = new MvxIocOptions();
// initialize the IoC registry, then add it to itself
var iocProvider = MvxSimpleIoCContainer.Initialize(options);
Mvx.RegisterSingleton(iocProvider);
}
}

Getting started with rhino service bus

I've read a lot of examples/tutorials (incl. Ayende's Alexandria on MSDN).
But just getting somewhat updated assemblies have proven to be an obstacle in itself. After getting the correct version of Castle.Windsor - it cannot find the correct section in the app.config file. The syntax in both Rhino Service Bus and the CastleBootstrapper has been changed as well - and I'm now totally confused. The 'documentation' on Hibernating Rhinos is really not helping me get started.
Could anyone please help me a working sample with Rhino Service Bus with either Castle Windsor v. 3.0 (beta) or 2.5.3, point me at something already online or just giving me a step-by-step pointers on what I need to get up and running?
after downloading the latest Rhino-ESB bits from github (https://github.com/hibernating-rhinos/rhino-esb) and building it, it's pretty straightforward to get started.
I have a asp.net MVC application which communicates with a backend through Rhino-ESB.
On the asp.net MVC side:
On global.asax.cs:
private IWindsorContainer _container;
protected void Application_Start()
{
_container = new WindsorContainer();
new RhinoServiceBusConfiguration().UseCastleWindsor(_container).Configure();
_container.Install(new YourCustomInstaller());
//Don't forget to start the bus
_container.Resolve<IStartableServiceBus>().Start();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));
}
Note that YourCustomInstaller must implement IWindsorInstaller and you register your controllers with the container in the Installmethod:
public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
container.Register(Component
.For<HomeController>().LifeStyle.PerWebRequest.ImplementedBy<HomeController>());
Also note that the WindsorControllerFactory internally delegates controller creation to the container:
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
return (IController)this.container.Resolve(controllerType);
}
Last but not least, provide the configuration on your web.config
<configSections>
<section name="rhino.esb" type="Rhino.ServiceBus.Config.BusConfigurationSection, Rhino.ServiceBus"/>
</configSections>
<rhino.esb>
<bus threadCount="1"
numberOfRetries="5"
endpoint="rhino.queues://localhost:31316/Client"
queueIsolationLevel="ReadCommitted"
name="Client"/>
<messages>
<add name="YourMessagesNamespace"endpoint="rhino.queues://localhost:31315/Backend"/>
</messages>
</rhino.esb>
This configuration assumes that the backend runs a queue in localhost:31315 and the client runs its queue on localhost:31316.
On the backend side:
assuming we're running it as a console application,
static void Main(string[] args)
{
IWindsorContainer container;
container = new WindsorContainer();
new RhinoServiceBusConfiguration()
.UseCastleWindsor(container)
.Configure();
var host = new RemoteAppDomainHost(typeof(YourBootstrapper));
host.Start();
Console.WriteLine("Starting to process messages");
Console.ReadLine();
Notice that YourBootstrapperclass implements CastleBootstrapper
public class YourBootstrapper: Rhino.ServiceBus.Castle.CastleBootStrapper
{
protected override void ConfigureContainer()
{
Container.Register(Component.For<OneOfYourMessages>());
}
}
in which we're registering a consumer for OneOfYourMessages

The type or namespace name 'MicroKernel' does not exist in the namespace 'Castle' (are you missing an assembly reference?)

I'm new to castle windsor and wanted to learn it.
I downloaded Windsor 2.5.3 for .net4 from here http://www.castleproject.org/castle/download.html
I built my first console app using vs2010 and try to play around.
The following are my code(very simple)
using Castle.Windsor;
using Castle.MicroKernel.Registration;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
WindsorContainer wc = new WindsorContainer();
wc.Register(Component.For<I>().ImplementedBy<C>());
var v = wc.Resolve<I>();
var result = v.M();
}
}
public class C : I
{
public string P1 { get; set; }
public int M()
{
return 100;
}
}
public interface I
{
int M();
}
}
But it didn't get compiled, error msg says:
The type or namespace name 'MicroKernel' does not exist in the namespace 'Castle' (are you missing an assembly reference?)
The type or namespace name 'Windsor' does not exist in the namespace 'Castle' (are you missing an assembly reference?)
I actually referenced castle.core and castle.windsor dlls and intellisense was working fine until compile....
I also noticed that when I double click the castle.windsor in reference, it's not showing the namespace hierarchy in object browser window.
I even commented out all my code, it still can't compile, says the same error msg.
Can you please advise what can I do to make it run. really appreciate it!!
The problem is likely the target framework of your project.
Open project properties, and look for the target framework dropdown. If it says .Net Framework 4.0 Client Profile, change it to .Net Framework 4.0.