这是我的故事:
我正在研究一个不那么大的WPF / C#应用程序,它在Unity Framework的帮助下实现(第一次)控制反转。它大部分都已完成。我的问题来自我的" bootstrapper" class,我在Unity容器中注册我的类型。由于所涉及的课程数量很多,我的引导程序变得比我想要的长得多,尽管有评论/地区,维持它对我以外的任何人来说都是一种痛苦。所以我想知道是否有更好的方法来处理注册。我在想,也许是:
1。 "你在抱怨什么?每个人都这样做" 嗯,我怀疑它
2。我误解了ioc的兴趣,而且我的课程中有太多需要注册。那么,ioc的兴趣是什么?
第3。我只是创建了一个包含太多不同类的馄饨应用程序,我应该合并一些我认为我尽力找到一个平衡
4.我不应该有一个宏引导程序,但主程序应该调用专用程序,一个通过librairy例如好的,开始听起来不错。毕竟,图书馆本身应该比其他人更了解它们包含的内容。但我绝对不知道如何处理它而不会让我的容器在每个库中流淌,这些都依赖于Unity ......
那么,这一点是好的,还是我只是错过了关于处理注册的好方法的帖子,以及任何人都使用的可维护性的舒适度?
PS:我没有在标签中提到过technos,因为对于使用ioc容器的每个应用来说这个问题似乎很常见
它是一个旧版本,它现在已经变长了,比如+ 15-20%
class Bootloader
{
public void Run()
{
#region SPLASH SCREEN
Sequenceur.IHM.Views.SplashScreen screen = new Sequenceur.IHM.Views.SplashScreen();
SplashScreenViewModel screenVM = new SplashScreenViewModel();
screen.Show();
#endregion
#region CONTAINER INITIALIZATION
UnityContainer container = new UnityContainer();
container.RegisterType<IMainWorker, Overseer>();
#endregion
#region DAL REGISTERATION
container.RegisterType<IManageData<Product>, LazyProductFilesManager>();
container.RegisterType<IManageData<Program>, LazyProgramFilesManager>();
container.RegisterType<IManageData<SequenceResult>, LazyResultFilesManager>();
#endregion
#region BOL REGISTERATION
//Sequence preparation
container.RegisterType<IProvideProducts, EagerCancellableProductProvider>();
container.RegisterType<IProvidePrograms, EagerCancellableProgramProvider>();
container.RegisterType<IPrepareSequence, SequenceInitializer>();
//Sequence processing
container.RegisterType<IManagePlugins, MefPluginManager>(new ContainerControlledLifetimeManager());
//Result Persistence
container.RegisterType<IPersistSequenceResult, SequenceResultPersister>();
container.RegisterType<IManageReport, Reporter>(new ContainerControlledLifetimeManager());
#endregion
#region UPDATE REGISTERATION
container.RegisterType<IManageConnection, SqlConnectionManager>();
container.RegisterType<IUpdateProducts, ProductsUpdater>();
container.RegisterType<IUpdatePrograms, ProgramsUpdater>();
container.RegisterType<IUploadResults, ResultsUploader>();
container.RegisterType<IUpdate, DevelopmentUpdater>(new ContainerControlledLifetimeManager());
#endregion
#region HELPERS REGISTERATION
//Hashing
container.RegisterType<IHashString, Sha256StringHasher>();
//Configuration
container.RegisterType<IPersistConfiguration, ConfigurationPropertiesPersister>();
container.RegisterType<IConfiguration, EditableConfiguration>();
//Logging
container.RegisterType<IManageLoggers, NLoggerManager>();
//Messengers
container.RegisterType<IMessagePublisher<Exception>, SimpleMessenger<Exception>>(new ContainerControlledLifetimeManager());
container.RegisterType<IMessagePublisher<AbortRequest>, SimpleMessenger<AbortRequest>>(new ContainerControlledLifetimeManager());
container.RegisterType<IMessagePublisher<ConfigData>, SimpleMessenger<ConfigData>>(new ContainerControlledLifetimeManager());
container.RegisterType<IMessagePublisher<SequenceAction>, SimpleMessenger<SequenceAction>>(new ContainerControlledLifetimeManager());
container.RegisterType<IMessagePublisher<UpdaterStatus>, SimpleMessenger<UpdaterStatus>>(new ContainerControlledLifetimeManager());
container.RegisterType<IMessageListener<AbortRequest>>();
#endregion
#region IHM REGISTERATION
container.RegisterType<ILoadMenuViews, SimpleMenuViewLoader>();
container.RegisterType<IManageScene, SceneManager>();
container.RegisterType<IProvideOD, WinFormOFDialog>();
#endregion
#region CONVERTERS REGISTERATION
container.RegisterType<IConvertModels<Parameter, dbParameterResult>, ParameterModelsConverter>();
container.RegisterType<IConvertModels<SequenceActionResult, dbActionResult>, ActionModelsConverter>();
container.RegisterType<IConvertModels<Tag, dbTag>, TagModelsConverter>();
container.RegisterType<IConvertModels<Country, dbCountry>, CountryModelsConverter>();
container.RegisterType<IConvertModels<Segment, dbSegment>, SegmentModelsConverter>();
container.RegisterType<IConvertModels<Caracteristic, dbCaracteristic>, CaracteristicModelsConverter>();
container.RegisterType<IConvertModels<Value, dbValue>, ValueModelsConverter>();
container.RegisterType<IConvertModels<Range, dbRange>, RangeModelsConverter>();
container.RegisterType<IConvertModels<Subrange, dbSubrange>, SubrangeModelsConverter>();
container.RegisterType<IConvertModels<Product, dbProduct>, ProductModelsConverter>();
container.RegisterType<IConvertModels<Program, dbProgram>, ProgramModelsConverter>();
container.RegisterType<IConvertModels<Tag, dbTag>, TagModelsConverter>();
#endregion
#region START
ShellView mainView = new ShellView();
mainView.DataContext = container.Resolve<ShellViewModel>();
screen.Close();
mainView.Show();
#endregion
}
}
答案 0 :(得分:2)
着名的Mark Seemann撰写了一篇博客文章,解释when to use a DI container。他基本上说的是,当只使用“显式注册”时,DI容器的用处是有限的,在容器中每个注册类型都有一行代码(这就是你正在做的事情)。当您使用约定优于配置时,真正的好处就开始了。使用约定优于配置,您将能够在一行代码中注册大量类型,并防止组合根成为此维护噩梦。
虽然我并不完全在同一页面上,但看到“明确注册”的使用情况。模型,他是正确的,你从使用约定优于配置获得最大的好处。在您的应用程序中,已经有一些明确的位置,您可以从约定优于配置中受益,以及在注册IManageData<T>
,IConvertModels和IMessagePublisher<TMessage>
等通用抽象时。
所以你可以做的是创建以下方便的扩展方法:
public static void RegisterManyForOpenGeneric(this UnityContainer container,
Type openGenericServiceType, params Assembly[] assemblies)
{
container.RegisterTypes(
from type in AllClasses.FromAssemblies(assemblies)
where type.GetInterfaces().Any(i => i.IsGenericType &&
i.GetGenericTypeDefinition() == openGenericServiceType)
select type,
WithMappings.FromMatchingInterface,
WithName.Default);
}
使用此扩展方法,您可以将通用抽象的注册减少到以下内容:
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
container.RegisterManyForOpenGeneric(typeof(IManageData<>), assemblies);
container.RegisterManyForOpenGeneric(typeof(IConvertModels<,>), assemblies);
container.RegisterManyForOpenGeneric(typeof(IMessagePublisher<>), assemblies);