2

通过 Autofac,可以很容易地将静态值注入到CurrentDate给定程序集中的类实例中:

builder.RegisterApiControllers(asm).WithProperty("CurrentDate", new DateTime(2012, 1, 13));

但是,如何将动态值(例如 a 返回的值)注入lamda () => { return DateTime.Now; }属性CurrentDate

4

4 回答 4

1

听起来您可以使用非常标准的属性注入,如下所示:

builder.RegisterApiControllers(asm)
    .OnActivating(e => { e.Instance.CurrentDate = DateTime.Now; });

请注意,您可能需要强制转换e.Instance,因为它可能是 Object 类型。

有关更多信息,请参阅文档中的 Lifetime Events 。

再想一想,为什么不把初始化放在基类构造函数中呢?

public DateTime CurrentDate { get; private set; }
protected ApiController() { CurrentDate = DateTime.Now; }

当前日期并不是您需要 DI 容器提供的真正依赖项。

于 2013-04-21T17:16:09.907 回答
0

您需要像这样编写自定义参数:

public class DelegateParameter : Parameter
{
    private readonly string _name;
    private readonly Func<object> _getValue;

    public DelegateParameter(string name, Func<object> getValue)
    {
        if (name == null) throw new ArgumentNullException("name");
        if (getValue == null) throw new ArgumentNullException("getValue");
        _name = name;
        _getValue = getValue;
    }

    public override bool CanSupplyValue(ParameterInfo pi, IComponentContext context, out Func<object> valueProvider)
    {
        PropertyInfo propertyInfo = GetProperty(pi);
        if (propertyInfo == null || propertyInfo.Name != _name)
        {
            valueProvider = null;
            return false;
        }
        valueProvider = _getValue;
        return true;
    }

    private static PropertyInfo GetProperty(ParameterInfo pi)
    {
        var methodInfo = pi.Member as MethodInfo;
        if (methodInfo != null && methodInfo.IsSpecialName && (methodInfo.Name.StartsWith("set_", StringComparison.Ordinal) && methodInfo.DeclaringType != null))
            return methodInfo.DeclaringType.GetProperty(methodInfo.Name.Substring(4));
        return null;
    }
}

然后使用它:

builder.RegisterApiControllers(asm).WithProperty(new DelegateParameter("CurrentDate", () => DateTime.Now));
于 2013-04-20T06:41:38.943 回答
0

注册另一个提供您的动态值的服务(例如IDateTimeService)[我认为它确实比您想要的 DateTime 更复杂。] 这个新服务的默认生命周期将是每个依赖项的实例,但您可以使用“Per Matching Lifetime Scope”。您的控制器将已根据 Http 请求创建。

IDateTimeService现在只需在(在构造函数中)添加来自控制器的依赖项。在该控制器中的方法中,您现在可以从该服务中获取您想要的动态值。

private static readonly IDateTimeService datetimeService;

public MyController (IDateTimeService datetimeService)
{
   this.datetimeService = datetimeService;
}


public void SomeMethod()
{
     var date = datetimeService.GetDate();
     ...
}
于 2013-04-20T04:29:07.700 回答
-1

如果您尝试注入 lambda 表达式,而不是 lambda 表达式的结果,那么您有很多不完美的选择。这里仅仅是少数; 我敢肯定还有更多。

自动法

Google Project Hosting 上的 Autofac wiki记录了四种注入属性的方法。其中三个似乎使用常量或默认值——您提到了其中一种方法。

最终似乎让开发人员对属性有更多的控制权。它使用OnActivating事件,在此期间您有几个选项。你可以:

  • 设置属性并希望它坚持下去。
  • 如果该属性缺少可访问的设置器,您可以使用反射来设置它,或者它的支持属性(默认情况下,m_PropertyName 用于名为 PropertyName 的属性,如果我没记错的话)。
  • 正如他们所说,将实例包装在代理中:请参阅下面的多态性

多态性

ClassA包含要修改的属性,Prop1。创建一个ClassB扩展的新类ClassA。如果Prop1virtual修饰符,您可以覆盖它。否则,使用new修饰符创建ClassB包含动态代码的类似属性。

在覆盖的情况下,您将需要实例化ClassB来代替ClassA. 如果框架创建了自己的 实例,这将不起作用ClassA,但只要您创建自己的实例ClassB并将它们传递给框架,就可以了。

如果您使用的是新属性,除了实例化之外ClassB,您还必须确保每当您访问新属性时,对象都被强制转换ClassB为后代类型。如果另一个框架被设计为使用,这通常不起作用ClassA,因为它总是在 type 上运行ClassA,而不是ClassB,不管你的转换如何。

字节码操作

这是令人讨厌的东西,但它会做你想要的。C# 通常编译为称为 CIL 的汇编/字节码语言。Microsoft 的变体是 MSIL,但它与通用 CIL 几乎相同。

我一直使用Mono.Cecil进行 CLI/CLR(.NET、Mono)字节码操作。它似乎完美无缺,一旦你掌握了它,它就会非常好。但是,您必须知道两件事:

  1. 如何使用 CIL
  2. 如何使用 Mono.Cecil

第一个没那么糟糕。只要您有足够的 CLI 经验,您就只需要几个带有详细表格的 Wikipedia 页面。如果您认为 CLI 仅代表“命令行界面”,那么您可能会遇到困难。

另一方面,截至大约一年前(2012 年),Mono.Cecil 缺乏任何形式的适当文档。学习曲线非常陡峭。我苦苦挣扎了几天试图弄清楚。不过,当它起作用时,它是惊人的。

于 2013-04-20T03:43:34.867 回答