8

好吧,我不知道“强命名”是否正确,但我想做的如下。

目前我使用 ConstructorArgument 像这样:

public class Ninja
{
    private readonly IWeapon _weapon;
    private readonly string _name;

    public Ninja(string name, IWeapon weapon)
    {
        _weapon = weapon;
        _name = name;
    }
    // ..more code..
}

public void SomeFunction()
{
    var kernel = new StandardKernel();
    kernel.Bind<IWeapon>().To<Sword>();
    var ninja = kernel.Get<Ninja>(new ConstructorArgument("name", "Lee"));
}

现在,如果我重命名参数“name”(例如使用 ReSharper),ConstructorArgument 将不会更新,并且在创建 Ninja 时会出现运行时错误。要解决此问题,我需要手动查找通过 ConstructorArgument 指定此参数的所有位置并更新它。不好,即使我有很好的测试覆盖率,我也注定会在某些时候失败。重命名应该是一种廉价的操作。

有什么方法可以改为引用参数 - 以便在重命名参数时更新它?

4

3 回答 3

5

如果您可以分享更多您真正想要实现的目标,您将获得更好的答案。一般来说,如果有帮助的话,你根本不想依赖传递 ConstructorArgument - 它应该是最后的手段,将参数值硬塞到创建你不拥有的组件中,因此可以依赖不在重构活动期间被重命名为 [as] willy nilly。因此,对于普通代码,如果您可以尝试将其保留在接口中以使事情明确而不依赖于更好的名称。

现在无法举出一个例子,但是有一个很常见的成语叫做静态反射。提供的 ConstructorArgument 可以在任何构造函数中匹配该名称的任何参数,因此静态反射在这种情况下不是最合适的。

因此,静态反射可能允许您实现的最佳效果是:

var ninja = ninject.Get<Ninja>( ParamNamesOf(()=>new Ninja( "dummy", "dummy" )).First() );

您将看到的典型示例是要提取实例上正在访问的属性的名称。这有点不同,因为它需要在构造函数调用表达式上工作。

至于找到一个已经拥有的合适的库,请为搜索者练习:D(但我建议找到一种更好的方法来表达你想做的事情,ConstructorArgument无论如何都不会优先使用这种方法。)

于 2010-04-14T12:30:15.160 回答
4

正如您已经注意到的那样,这种方法非常脆弱,应该避免使用。如果您不需要将名称添加为构造函数参数,请尝试设计。例如,您可以这样做:

public class Ninja
{
    private readonly IWeapon _weapon;

    public Ninja(IWeapon weapon)
    {
        _weapon = weapon;
    }

    public string Name { get; set; }

    // ..more code..
}

public void SomeFunction()
{
    var kernel = new StandardKernel();
    kernel.Bind<IWeapon>().To<Sword>();
    var ninja = ninject.Get<Ninja>();
    ninja.Name = "Lee";
}

我希望这有帮助。

于 2010-04-14T12:03:39.577 回答
0

是的你可以。

我已经实现了这个:

    public string GiveConstuctorArgumentName(Type class, Type constructorArgument)
    {
       var cons = class.GetConstructors();

       foreach (var constructorInfo in cons)
       {
          foreach (var consParameter in constructorInfo.GetParameters())
          {
             if (consParameter.ParameterType == constructorArgument)
             {
                return consParameter.Name;
             }
          }
       }

       throw new InstanceNotFoundException();
    }

它没有 LINQ,但它是了解其工作原理的良好起点。

于 2013-02-20T12:48:39.590 回答