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

发布于 2024-07-09 21:16:59 字数 447 浏览 6 评论 0 原文

我想在 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>

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

黄昏下泛黄的笔记 2024-07-16 21:16:59

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

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

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

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

不幸的是,由于组件模型中的参数是不可变的,您通常无法通过更简单的方法(例如模型创建内核事件)来做到这一点。

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.

情绪操控生活 2024-07-16 21:16:59

您不能仅从 xml 进行这样的设置。 但是您可以使用 工厂设施 来做到这一点。

You can't set it up like that from xml alone. But you could use the factory facility to do this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文