Help with Castle Windsor XML configuration - castle-windsor

I have the following three components defined in the Caste-Windsor XML configuration for my application:
<component id="StringFactory"
service="IStringFactory, MyApp"
type="DefaultStringFactory, MyApp"
lifestyle="singleton"
/>
<component id="TheString"
type="System.String"
factoryId="StringFactory"
factoryCreate="CreateString"
>
<parameters>
<name>SomeString</name>
</parameters>
</component>
<component id="TheTarget"
service="ITarget, MyApp"
type="TheTarget, MyApp"
lifestyle="transient"
>
<parameters>
<aString>${TheString}</aString>
</parameters>
</component>
And the following facility defined:
<facility id="factory.support"
type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel"
/>
When I run the application and set a breakpoint in the constructor of the TheObject class, the value passed in as the aString parameter is "${TheString}" when I expect it to resolve to the value of the component with that name.
Also, I have a breakpoint in the StringFactory constructor and CreateString method, neither of which are hit. I know the configuration is being used as other components are resolving correctly.
What am I missing or doing wrong here?
UPDATE
In light of the huge tangient this topic has taken, I've refactored the code above to remove anything to do with connection strings. The original intent of this post was about injecting a property with the value returned from a method on another object. Somehow that point was lost in a discussion about why I'm using XML versus code-based configuration and if this is a good way to inject a connection string.
The above approach is far from an original idea and it was pulled from several other discussions on this topic and our requirements are what they are. I'd like help understanding why the configuration as it is in place (whether the right approach or not) isn't working as expected.
I did verify that the first two components are being instantiated correctly. When I call Container.Resolve("TheString"), I get the correct value back. For whatever reason, The parameter syntax is not working correctly.
Any ideas?

While not a definitive solution to what I need to do in my application, I believe I've figured out what is wrong with the code. Or at least I've found a way to make it work which hints at the original problem.
I replaced the String type for TheString with a custom class. That's it. Once I did that, everything worked fine.
My guess is that it has something to do with the fact that I was trying to use a ValueType (primitive) as a component. I guess Castle doesn't support it.
So, knowing that's the case, I can now move on to figuring out if this approach is really going to work or if we need to change direction.
UPDATE
For the sake of completeness, I thought I'd go ahead and explain what I did to solve my problem AND satisfy my requirements.
As before, I have access to my configuration settings through an IConfigurationService defined as:
<component id="ConfigurationService"
service="MyApp.IConfigurationService, MyApp"
type="MyApp.RuntimeConfigurationService, MyApp"
lifestyle="singleton"
/>
This is automatically injected into my (new) IConnectionFactory which is responsible for generating IDbConnection objects based on the connection strings defined in the application's configuration file. The factory is declared as:
<component id="ConnectionFactory"
service="MyApp.Factories.IConnectionFactory, MyApp"
type="MyApp.Factories.DefaultConnectionFactory, MyApp"
lifestyle="singleton"
/>
In order to resolve what connection is used by my repository, I declare each connection as a component using the ConnectionFactory to create each instance:
<component id="MyDbConnection"
type="System.Data.IDbConnection,
System.Data, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"
factoryId="ConnectionFactory"
factoryCreate="CreateConnection"
lifestyle="transient"
>
<parameters>
<connectionStringName>MyDB</connectionStringName>
</parameters>
</component>
Notice the fully described reference to System.Data. I found this is necessary whenever referencing assemblies in the GAC.
Finally, my repository is defined as:
<component id="MyRepository"
service="MyApp.Repositories.IMyRepository, MyApp"
type="MyApp.Sql.SqlMyRepository, MyApp.Sql"
lifestyle="transient"
>
<parameters>
<connection>${MyDbConnection}</connection>
</parameters>
</component>
Now everything resolves correctly and I don't have ANY hard-coded strings compiled into my code. No connection string names, app setting keys or whatever. The app is completely reconfigurable from the XML files which is a requirement I must satisfy. Plus, other devs that will be working with the solution can manage the actual connection strings in the way they are used to. Win-win.
Hope this helps anyone else that runs into a similar scenario.

You don't really need XML registrations here, since you probably don't need to swap components or change the method used without recompiling. Writing a configurable app does not imply having to use XML registrations.
The problem with this particular XML registration you posted is that the connection string is a parameter, but it's treated like a service.
Doing this with code registrations is much easier, e.g.:
var container = new WindsorContainer();
container.Register(Component.For<IConfigurationService>().ImplementedBy<RuntimeConfigurationService>());
container.Register(Component.For<ITheRepository>().ImplementedBy<TheRepository>()
.LifeStyle.Transient
.DynamicParameters((k, d) => {
var cfg = k.Resolve<IConfigurationService>();
d["connectionString"] = cfg.GetConnectionString();
k.ReleaseComponent(cfg);
}));
Or if you don't want to depend on IConfigurationService, you could do something like:
container.Register(Component.For<ITheRepository>().ImplementedBy<TheRepository>()
.LifeStyle.Transient
.DependsOn(Property.ForKey("connectionString")
.Is(ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["connName"]].ConnectionString))

Related

PhpStorm unable to resolve symbol 'doctrine.orm.entity_manager'

When I open the services.xml in PhpStorm with Symfony Plugin enabled, it's able to resolve all the services, I can Ctrl+Click and go the Service Definition , except doctrine.orm.entity_manager.
It says unable to resolve symbol 'doctrine.orm.entity_manager'
Here is the services.xml file
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="example_manager" class="Vendor\XysBundle\Manager\ExampleManager">
<argument type="service" id="doctrine.orm.entity_manager" />
</service>
</services>
</container>
PhpStorm Details:
PhpStorm 2016.3.1
Build #PS-163.9735.1, built on December 6, 2016
JRE: 1.8.0_112-release-408-b2 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
appDevDebugProjectContainer.xml file exists in the app/cache directory .
How can I get get this working ?
I have the same issue. If you open up the vendor\doctrine\doctrine-bundle\Resources\config\orm.xml file where doctrine services are defined, you can see, there is no service with the id "doctrine.orm.entity_manager" but only "doctrine.orm.entity_manager.abstract"
The definition looks like:
<service id="doctrine.orm.entity_manager.abstract" class="%doctrine.orm.entity_manager.class%" abstract="true" />
As you can see the abstract attribute is set to true. This means this service can serve as a parent of other services, and when you define child services with this abstract parent you don't have to define the method calls or the parameters injected into the constructor for example, instead these definitions will be inherited from the parent.
If you investigate a bit deeper you will find that %doctrine.orm.entity_manager.class% is defined in the same file as a parameter that actually references to the Doctrine Entity Manager:
<parameter key="doctrine.orm.entity_manager.class">Doctrine\ORM\EntityManager</parameter>
So I guess we should use doctrine.orm.entity_manager.abstract, however doctrine.orm.entity_manager is recognised as well, although I don't know how.
For further explanation of abstract service definitions have a look at this Symfony doc page: https://symfony.com/doc/current/service_container/parent_services.html

Windsor installer configuration

I have an application built with Windsor, this application has features and al the components are manually registered inside xml which also contains their configuration. This is an example:
<component type="type">
<parameters>
[...]
</parameters>
</component>
I decided to refactor my components and separate them into windsor installers, one installer for each feature. My problem now is to decide where to put the configuration of the components registered inside each installer.
Before this decision, the user could find the appropriate configuration of the components mostly inside the parameters element of xml, and I did not have to write wire logic for that to work.
Now I'm a bit confused because it seems like I don't have anymore such automatism. Since I decided to declare the installers of my application by xml, I think it could be perfect if I could put this configuration inside the installr element like this:
<installers>
<install assembly="myassembly">
<parameters>
[...]
<parameters>
</install>
</installers>
I don't know if Windsor supports this syntax. If it does, then I wonder how I could access it from inside the installer and how to wire it up to my components and services.
Another accettable alternative could be to create and register on xml a component containing all the configuration of my feature:
<components>
<component type="featureConfiguration">
<parameters>
</parameters>
</component>
</components>
In this case I guess that I have to refactor my components to let them receive such type as argument in their constructor whereas before I had direct properties, in other words before I could tell exactly what were the dependencies of my components by looking at the code, with this new form I pass to them the whole configuration but I don't know anymore what specific properties of the configuration are used in this or that component.
To use this second solution and to avoid this confusion I should avoid to pass the whole configuration to my subcomponents, and let that single properties do the work, but I have to find a glue between the properties of this configuration component and the properties of the components and services of the installer.
I think that rather than a component I could also put all my configuration inside the properties element of xml:
<properties>
<featureConfiguration>
[property list]
</featureConfiguration>
</properties>
but again, I have to find the glue between each single property in the list and the properties of my components.
Any help is appreciated.
Thank you.
Maybe you will find this mixed solution helpful, depending on the level of the parameterization of your components that you need. Namely, you could perform the component registration in your installers and set the parameters of the components in a windsor config file. This is useful when you have parameterization needs on few of your components while letting Windsor handle all other dependencies.
Example:
Let's say that you have the following components.
public class MyComponent
{
public MyComponent(MyDependency dependency, string stringParameter, DateTime dateParameter)
{
this.Dependency = dependency;
this.StringParameter = stringParameter;
this.DateParameter = dateParameter;
}
public DateTime DateParameter { get; set; }
public string StringParameter { get; set; }
public MyDependency Dependency { get; set; }
}
public class MyDependency
{
}
Then you could use the following installer to register them.
public class MyInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<MyComponent>().Named("MyComponent"));
container.Register(Component.For<MyDependency>());
}
}
Note, that we have been explicit about the unique name of the component, set to MyComponent. But you can use also the default full name.
The windsor config file could look like this:
<configuration>
<components>
<component id="MyComponent">
<parameters>
<stringParameter>Some string</stringParameter>
<dateParameter>2013/09/25</dateParameter>
</parameters>
</component>
</components>
</configuration>
And now you can wrap it all together:
WindsorContainer container = new WindsorContainer();
container.Install(Configuration.FromXmlFile("windsor.config"));
container.Install(FromAssembly.This());
Note that the order of invoking the Install method is important; you must first install the config file settings.

Spring.NET PropertyPlaceholderConfigurer using ${my value}

My Spring.NET configuration is using the following type syntax and is working ok.
<object id="JohnUsingVariableSource"
type="XmlConfig.StringInjection.Person, XmlConfig">
<property name="Name" value="${JohnsFullName}" />
</object>
Values for the ${JohnsFullName} placeholder are configured in the app.config file. My requirements have changed and I know need to get the name from the database at startup. How is it possible to overwrite the value in the app.config file ? Can I do it in code without opening the app.config (as here App.Config change value), does spring.NET have a way of doing this ?
Yes, you can do that without modifying the app.config file. Simply implement a custom IVariableSource:
public interface IVariableSource
{
string ResolveVariable(string name);
}
In the ResolveVariable method you read from the db.
The first variable source configured in your config will be the one used by the spring config, if I recall correctly.

Log4net - log parts of code, used in a couple of methods

I have some trouble.
My application could be divided to 3 logical parts (import, processing and export). There are some parts of code which are used in several parts of my application. How can I determine which part of code called my log4net object?
What is best practice to log info in parts of code which are called from several places in the application?
I want to turn on and off the ability to log parts of my application from a config file.
If I turn off logging for the processing part of my app, how could I log info in the export part of my app when both of them use one method, in which I initialize my logger object?
You could add a separate logger for each section of your app that you want to log and then turn them off and on as needed. They would all be independent from one another and this can all be setup via the config.
By setting the additivity property to false, the loggers will all be independent of one another. Here's an example of the config portion:
<logger name="Logger1" additivity="false">
<level value="INFO" />
<appender-ref ref="Logger1File" />
</logger>
To use it in your code, reference it like this:
private static ILog _Logger1= LogManager.GetLogger("Logger1");
Anything you log to Logger1 will be separate from any other logger, including the root one.
log4net provides contexts for this purpose. I would suggest using a context stack like this:
using(log4net.ThreadContext.Stacks["Part"].Push("Import"))
log.Info("Message during importing");
using(log4net.ThreadContext.Stacks["Part"].Push("Processing"))
log.Info("Message during processing");
using(log4net.ThreadContext.Stacks["Part"].Push("Export"))
log.Info("Message during exporting");
The value on the stack can be shown in the logs by including %property{Part} in a PatternLayout.

Unity IOC Configuration

I have a class
public class Broker
{
public Broker(string[] hosts, string endPoint, string port, Type remoteType)
{
}
}
Which I want to configure using Unity XML Configuration, I can configure it using code in C# as follows already, where "container" is my Unity container
container.Configure<InjectedMembers>()
.ConfigureInjectionFor<Broker>("myBroker",
new InjectionConstructor(hosts, endPoint, port, new InjectionParameter(typeof(IMyBrokeredObject))));
and it will happly resolve using the normal unity calls
container.Resolve("myBroker");
But currently my xml cannot resolve the final parameter IMyBrokeredObject, I get a resolution exception, as Unity is trying to resolve the type insted of simply injecting the type, as it does in the code above.
Any Ideas?
Have you defined the type in the configuration file:
<unity>
<typeAliases>
<typeAlias alias="IMyBrokeredObject" type="MyAssembly.IMyBrokeredObject, MyAssembly" />
</typeAliases>
<containers>
<container>
<types>
<!-- Views -->
<type type="IMyBrokeredObject" mapTo="MyAssembly.MyBrokeredObjectImplementation, MyAssembly" />
But my problem is that there is no implementation available for the IMyBrokeredObject, what is actually happening in the background of this is that the broker provides remote objects given an interface, the actual implementation is somewhere else.
In code I can get the container to provide an broker by giving an "InjectionParameter", I cannot find out how to do this in the xml configuration.
its tricky because I dont want the container to give an instance of the interface but to actually pass the interface as is, the "InjectionParameter" is a store for a value, the stored value is handed in when the object is created by the container, as is. What I am looking for is the required configuration xml to create the InjectionParameter and give it the value, if that is at all possible?