I want to perform this CODE equivlant in the castle xml config file.
// Foo(string name)
IFoo f = new Foo(StaticBarClass.Name);
XML
Now for the XML, I know everything (e.g. the blah) except for the stuff inside the parameter part.
What would the parameter part look like?
<component id="blah"
service="blah"
type="blah">
<parameters>
<name>StaticBarClas.Name_THAT_I_NEED_HELP_WITH</name>
</parameters>
One approach you could use is to replace the configuration parameters inspector with your own variant that can introduce some additional behaviour - here's a quick prototype:
public class ExtendedConfigurationParametersInspector : IContributeComponentModelConstruction
{
#region IContributeComponentModelConstruction Members
public virtual void ProcessModel(IKernel kernel, ComponentModel model)
{
if (model.Configuration == null) return;
IConfiguration parameters = model.Configuration.Children["parameters"];
if (parameters == null) return;
foreach (IConfiguration parameter in parameters.Children)
{
String name = parameter.Name;
String value = parameter.Value;
if (value == null && parameter.Children.Count != 0)
{
IConfiguration parameterValue = parameter.Children[0];
model.Parameters.Add(name, parameterValue);
}
else
{
if (parameter.Attributes["type"] == "static")
{
int lastIndex = parameter.Value.LastIndexOf(".");
string typeName = parameter.Value.Substring(0, lastIndex);
string field = parameter.Value.Substring(lastIndex + 1);
Type ownerType = Type.GetType(typeName);
FieldInfo valueField = ownerType.GetField(field);
value = (string) valueField.GetValue(null);
}
model.Parameters.Add(name, value);
}
}
foreach (ParameterModel parameter in model.Parameters)
{
if (parameter.Value == null || !ReferenceExpressionUtil.IsReference(parameter.Value))
{
continue;
}
String newKey = ReferenceExpressionUtil.ExtractComponentKey(parameter.Value);
model.Dependencies.Add(new DependencyModel(DependencyType.ServiceOverride, newKey, null, false));
}
}
#endregion
}
public class ExtendedComponentBuilder : DefaultComponentModelBuilder
{
public ExtendedComponentBuilder(IKernel kernel) : base(kernel)
{
}
protected override void InitializeContributors()
{
AddContributor(new GenericInspector());
AddContributor(new ConfigurationModelInspector());
AddContributor(new ExtendedConfigurationParametersInspector());
AddContributor(new LifestyleModelInspector());
AddContributor(new ConstructorDependenciesModelInspector());
AddContributor(new PropertiesDependenciesModelInspector());
AddContributor(new LifecycleModelInspector());
AddContributor(new InterceptorInspector());
AddContributor(new ComponentActivatorInspector());
AddContributor(new ComponentProxyInspector());
}
}
public class ExtendedWindsorContainer : WindsorContainer
{
public ExtendedWindsorContainer(IConfigurationInterpreter interpreter)
: base(CreateKernel(), new Castle.Windsor.Installer.DefaultComponentInstaller())
{
if (interpreter == null) throw new ArgumentNullException("interpreter");
interpreter.ProcessResource(interpreter.Source, Kernel.ConfigurationStore);
RunInstaller();
}
private static IKernel CreateKernel()
{
DefaultKernel kernel = new DefaultKernel();
kernel.ComponentModelBuilder = new ExtendedComponentBuilder(kernel);
return kernel;
}
}
You could then wire up the properties in your container like so, where specifying a type of "static" for the parameter would cause the value to be replaced with the static field that was referenced by the parameters value.
<castle>
<components>
<component id="test"
type="SomeNamespace.TestComponent,Example">
<parameters>
<value type="static">SomeNamespace.SomeClass.TheStaticFieldValue</value>
</parameters>
</component>
</components>
</castle>
Unfortunately you generally can't do this through simpler means (such as the model created kernel event) due to the fact that parameters in the component model are immutable.
You can't set it up like that from xml alone. But you could use the factory facility to do this.
来源:https://stackoverflow.com/questions/381734/castle-windsor-how-to-specify-a-runtime-value-as-a-parameter-e-g-value-return