Castle Windsor:如何将运行时值指定为参数(例如静态函数调用返回的值)

时间:2008-12-19 18:09:07

标签: runtime castle-windsor parameters

我想在castle xml配置文件中执行此 CODE

// Foo(字符串名称)

IFoo f = new Foo(StaticBarClass.Name);




XML

现在对于XML,除了参数部分中的内容之外,我知道所有内容(例如,等等)。

参数部分是什么样的?

<component id="blah"
           service="blah"
           type="blah">
  <parameters>
    <name>StaticBarClas.Name_THAT_I_NEED_HELP_WITH</name>
  </parameters>

2 个答案:

答案 0 :(得分:1)

你不能单独从xml那样设置它。但您可以使用factory facility来执行此操作。

答案 1 :(得分:1)

您可以使用的一种方法是使用您自己的变体替换配置参数检查器,这可能会引入一些额外的行为 - 这是一个快速原型:

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;
  }
}

然后您可以像这样连接容器中的属性,其中为参数指定“static”类型将导致值被参数值引用的静态字段替换。

<castle>
  <components>
    <component id="test"
           type="SomeNamespace.TestComponent,Example">
      <parameters>
        <value type="static">SomeNamespace.SomeClass.TheStaticFieldValue</value>
      </parameters>
    </component>
  </components>
</castle>

不幸的是,由于组件模型中的参数是不可变的,因此通常无法通过更简单的方法(例如模型创建的内核事件)来执行此操作。