C# 有没有办法将操作注册到DI容器(Autofac)中?
在这种情况下,我需要向类的构造函数中注入一个操作。由于这种需要,我目前一直在整个应用程序中使用服务定位器模式,而不能简单地将DI容器用于预期目的 下面是一个例子 RootPage.cs(母版详细信息页) 现在我要做的是将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
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);