Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有没有办法将操作注册到DI容器(Autofac)中?_C#_Dependency Injection_Autofac - Fatal编程技术网

C# 有没有办法将操作注册到DI容器(Autofac)中?

C# 有没有办法将操作注册到DI容器(Autofac)中?,c#,dependency-injection,autofac,C#,Dependency Injection,Autofac,在这种情况下,我需要向类的构造函数中注入一个操作。由于这种需要,我目前一直在整个应用程序中使用服务定位器模式,而不能简单地将DI容器用于预期目的 下面是一个例子 RootPage.cs(母版详细信息页) 现在我要做的是将NavigationPage和DetailPage注册到容器中,然后使用一些自定义逻辑来解析泛型 PseudoRootPage.cs public RootPage() { this.Master = MyApp.PageBuilder < NavigationPa

在这种情况下,我需要向类的构造函数中注入一个操作。由于这种需要,我目前一直在整个应用程序中使用服务定位器模式,而不能简单地将DI容器用于预期目的

下面是一个例子

RootPage.cs(母版详细信息页)

现在我要做的是将
NavigationPage
DetailPage
注册到容器中,然后使用一些自定义逻辑来解析泛型

PseudoRootPage.cs

public RootPage()
{
    this.Master = MyApp.PageBuilder < NavigationPage > ();
    this.Detail = MyApp.PageBuilder < DetailPage > ();
}
public RootPage()
{
this.Master=MyApp.PageBuilder();
this.Detail=MyApp.PageBuilder();
}
问题在于我需要在DetailPage中执行的操作,以允许我切换导航菜单

有没有办法将操作注册到DI容器中


另一个选项是将OnTogglereRequest设置为
内部静态

听起来您需要的是一个

DetailPage
中,您创建了一个代理属性,该属性将充当页面的工厂。我还没有这样做,但您可能会将其设置为静态(作为工厂方法/委托)。我主要提供Autofac提供的示例,根据您的类型进行定制

public delegate Shareholding Factory(Action toggleRequest);
然后将详细信息页面注册到IoC容器中

var builder = new ContainerBuilder();
builder.RegisterType<DetailPage>();
var container = builder.Build();

希望这正是您想要的。

我不确定自己是否100%理解与
母版详细信息页相关的所有复杂性,但是使用AutoFac动态实例化如何

public class RootPage
{
   public RootPage(INavigationPage navigationPage,
      Func<Action, IDetailPage> detailPageFactory)
   {
      var detailPage = detailPageFactory(myAction);
   }
}
公共类根页面
{
公共根页面(INavigationPage导航页面,

Func

如果要注入的
操作的实现是静态的,那就很容易了。通常我们不会将静态方法和注入结合在一起,但是您依赖于一个可以替换的抽象,所以这一点都不重要

我建议声明一个与您的操作相对应的委托。否则,如果您必须要注入的操作都具有相同的签名,则它们将无法区分。这还可以更清楚地说明您注册的是什么

builder.Register<DelegateForSomeAction>(context => MyStaticClass.MyStaticMethod);
为了便于说明,下面是一个类,该类具有实现委托的方法:

public class AddsNumbers 
{
    public Single Add(Single value1, Single value2)
    {
        return value1 + value2;
    }
}
builder.RegisterType<AddsNumbers>();
builder.Register<DoMath>(c =>
{
    var componentContext = c.Resolve<IComponentContext>();
    var addsNumbers = componentContext.Resolve<AddsNumbers>();
    return addsNumbers.Add;
});
然后注册包含要注入的方法的类型:

builder.RegisterType<AddsNumbers>();
现在,实际的注册码要简单得多:

builder.RegisterDelegate<DoMath, AddsNumbers>(addsNumbers => addsNumbers.Add);
builder.RegisterDelegate(addsNumbers=>addsNumbers.Add);
扩展方法还有一些额外的参数,以备需要时使用

  • 已解析委托所在组件的命名实例
  • 命名要注册的代理组件
  • 两者
我更喜欢这种方法,因为如果你的类依赖于一个动作(委托),那么它就应该依赖于这个动作,而不是依赖于Autofac创建工厂所需的一些奇怪的接口。所有这些魔法都应该移到合成根,然后这个类就可以得到它想要的东西

builder.RegisterType<AddsNumbers>();
builder.RegisterType<AddsNumbers>();
builder.Register<DoMath>(c =>
{
    var componentContext = c.Resolve<IComponentContext>();
    var addsNumbers = componentContext.Resolve<AddsNumbers>();
    return addsNumbers.Add;
});
{ 
    public static IRegistrationBuilder<TDelegate, SimpleActivatorData, SingleRegistrationStyle> RegisterDelegate<TDelegate, TSource>( 
        this ContainerBuilder builder,  
        Func<TSource, TDelegate> extractDelegate,  
        string sourceComponentName = null,  
        string registeredComponentName = null)  
        where TDelegate : class
    {
        var registrationFunction = new Func<IComponentContext, TDelegate>(context => 
        { 
            var c = context.Resolve<IComponentContext>(); 
            var source = sourceComponentName == null 
                ? c.Resolve<TSource>() 
                : c.ResolveNamed<TSource>(sourceComponentName); 
            return extractDelegate(source); 
        }); 

        return registeredComponentName == null ? 
            builder.Register(registrationFunction) : 
            builder.Register(registrationFunction) 
                .Named<TDelegate>(registeredComponentName); 
    } 
}
builder.RegisterDelegate<DoMath, AddsNumbers>(addsNumbers => addsNumbers.Add);