2013-07-14 2 views
1

Есть ли какой-либо контейнер .NET DI, который имеет понятие «дочерние области»?Есть ли контейнер DI, который позволяет использовать «детские области»?

Что-то вроде:

var container = AppConfiguredContainer(); 

using(var childContainer = container.GetChild()) 
{ 
    childContainer.Register<IFoo>(typeof(Foo)); 

    // do stuff with childContainer 
} 

Дело в том, что любая конфигурация услуг, сделанных в детском контейнере не будет влиять на конфигурацию приложения шириной.

+1

Попробуйте Ninject - не уверенно на 100%. –

+0

Unity - [с использованием дочерних контейнеров] (http://msdn.microsoft.com/en-us/library/dn178463 (v = pandp.30) .aspx # sec25) –

+0

Что вы пытаетесь достичь? В большинстве контейнеров есть функция «образцовый образ жизни», который в большинстве случаев имеет тот же эффект. И для остальных случаев: вы не должны делать никаких регистраций после этапа запуска приложения. Я даже прочитал сообщение в блоге от Krzysztof Koźmic, что он сожалеет о том, что добавил эту функцию в Castle Windsor, поэтому я считаю, что такая функция действительно сомнительна. – Steven

ответ

0

Вот пример дочерних областей связывания с Ninject:

var k = new StandardKernel(); 
k.Bind<Application>().ToSelf().InSingletonScope().DefinesNamedScope("Application"); 
k.Bind<UserRepository>().ToSelf().InNamedScope("Application"); 

const string userScopeName = "User"; 
k.Bind<UserScope>().ToSelf().DefinesNamedScope(userScopeName); 
k.Bind<User>().ToSelf().InNamedScope(userScopeName); 
k.Bind<User.ChatService>().ToSelf().InNamedScope(userScopeName); 
k.Bind<User.SheetService>().ToSelf().InNamedScope(userScopeName); 

const string nestedScopeName = "UserSheet"; 
k.Bind<User.Sheet>().ToSelf().DefinesNamedScope(nestedScopeName); 
k.Bind<User.Sheet.SheetInfo>().ToSelf().InNamedScope(nestedScopeName); 
k.Bind<User.Sheet.SheetCalculator>().ToSelf().InNamedScope(nestedScopeName); 

Вы должны ссылаться Ninject.Extensions.NamedScope и Ninject.Extensions.Factory с Ninject.Extensions.ContextPreservatioon.

Каждый Repository может загружать несколько пользователей, и каждый из них будет иметь несколько Sheets в «суб-областей»:

public class UserRepository 
{ 
    Func<UserScope> _factory; 

    [Inject] 
    public UserRepository(Func<UserScope> factory) 
    { 
     _factory = factory; 
    } 

    public UserScope LoadUser() 
    { 
     return _factory(); // scopes preserved 
    } 
} 


public class User 
{ 
    Func<Sheet> _sheetFactory; // multiple instances inside User scope 
    public UserRepository Repository { get; } // same instance for app 
    [Inject] 
    public User(Func<Sheet> sheetFactory, UserRepository repository) 
    { 
     Repository = repository; 
     _sheetFactory = sheetFactory; 
    } 

    public Sheet MakeSheet() 
    { 
     return _sheetFactory(); 
    } 
} 

Это важно использовать UserScope класс в качестве контейнера для User, потому что в противном случае вы не можете решить тот же экземпляр User внутри его зависимостей:

public class UserScope : IDisposable 
{ 
    [Inject] 
    public UserScope(User user, IResolutionRoot resolver) 
    { 
     User = user; 
     Resolver = resolver; 
    } 

    public User User { get; } 
    public IResolutionRoot Resolver { get; } // you can use this to resolve anything from inside **this** user scope 
} 

Затем вы можете загрузить пользователей, как:

var app = k.Get<Application>(); // singleton 
var u1 = app.Repository.LoadUser(); 
var u2 = app.Repository.LoadUser(); 

И каждый из них будет иметь те же экземпляры Application и Repository, но разные экземпляры ChatService и SheetService.

Смежные вопросы