我有一个包含多个项目的解决方案(MyApp.Data,MyApp.BLL,MyApp.Web)。我在MyApp.Web(主Web应用程序)中的Global.asax文件中注册类型:
builder.RegisterType<SomeService1>().As<ISomeService1>().InstancePerHttpRequest();
builder.RegisterType<SomeService2>().As<ISomeService2>().InstancePerHttpRequest();
//...etc
我想知道使用其他程序集中的属性(例如,在MyApp.BLL中)注册类型及其范围是不好的做法。见下文:
[Dependency(typeof(ISomeService1), ComponentLifeStyle.Transient)]
public class SomeService1 : ISomeService1
{
//methods and properties go here
}
答案 0 :(得分:3)
使用本地属性或其他方式指示DI容器的连线将服务紧密耦合 DI容器,所以我认为这不是一个好主意。
此外,它可能会限制您未来的选择。例如,如果您指定生活方式范围,则不能重复使用具有不同范围的服务。
一般情况下,您应该在Composition Root(global.asax)中撰写应用程序,这会为您提供单一位置,其中明确定义的责任,其中所有课程都是由。
组成这样可以更容易管理,可维护,可以在整个课程中传播配置数据。
答案 1 :(得分:2)
正如您的问题所暗示的那样,将注册责任委派给知道需要注册的程序集是有道理的。例如,如果你 使用SolrNet库,它提供了一个执行组件注册的方法,以封装需要注册的内容的知识,并使库的消费者不必在开始之前了解库的所有信息。
但是,这种方法存在潜在问题。如果您在其他应用程序中使用从属程序集,您的注册要求是否会更改例如,将某些内容注册为ComponentLifeStyle.HttpRequestScoped
然后在非Web应用程序中使用它是否有意义?通过将注册委托给依赖项,您可以将依赖项与其使用者的注册要求(以及对IoC容器的选择)相关联。
Autofac(我不能代表其他IoC容器)为此提供了一种方法。它使您可以覆盖注册,以便在解析服务时使用最近注册的组件。这意味着您可以调用库的注册方法,然后注册您自己的服务以覆盖默认值。
您提议的基于属性的注册存在另一个问题 - 它不允许您将lambda表达式指定为组件创建者。你会如何用属性实现这样的注册?
builder.Register(c => new A(c.Resolve<B>()));
最好定义一个IRegistrar
接口,然后使用反射来搜索所有已加载的程序集以进行实现并调用它们。也许是这样的:
public interface IRegistrar
{
void RegisterComponents();
}