2017-07-13 1 views
1
vie

J'ai plusieurs projets dans ma solution:registre Interface dans le conteneur unité basée sur l'interface marqueur dans différentes

Core 
Repository 
Service 
WebAPi 

Inscription Mon unité est sur le projet WebAPI.

Ce que je suis en train de réaliser est quelque chose que je l'ai fait au château de Windsor, dans le passé, maintenant je veux le faire via l'unité: registre en utilisant l'interface convention https://github.com/castleproject/Windsor/blob/master/docs/registering-components-by-conventions.md

J'ai deux interfaces marqueurs.

public interface ISingletonDependency{} 
public interface ITransientDependency{} 

Pour les classes dans mon dépôt ou le service que je fais:

public interface IPersonRepository:ISingletonDependency{ 
... 
... 

} 

public class PersonRepository: IPersonRepository{ 
... 
... 
... 
} 

Dans ma classe de service:

public interface IPersonService:ISingletonDependency{ 
... 
...  
} 

public class PersonService: IPersonService{ 
... 
... 
... 
} 

Je le fais pour tous mes cours dans la même manière pour les DI et pendant l'enregistrement, j'avais l'habitude de faire:

container.Register(
    Classes.NamedAssembly("SolutionName.Repository") 
     .BasedOn<ISingletonDependency>() 
     .WithService.FromInterface().LifestyleSingleton() 
); 


container.Register(
    Classes.NamedAssembly("SolutionName.Service") 
     .BasedOn<ISingletonDependency>() 
     .WithService.FromInterface().LifestyleSingleton() 
); 


container.Register(
    Classes.NamedAssembly("SolutionName.Repository") 
     .BasedOn<ITransientDependency>() 
     .WithService.FromInterface().LifestyleTansient() 
); 


container.Register(
    Classes.NamedAssembly("SolutionName.Service") 
     .BasedOn<ITransientDependency>() 
     .WithService.FromInterface().LifestyleTansient() 
); 

De cette façon, je n'ai pas besoin de faire cela pour chacun, j'ai vu l'approche dans Unity, mais il se base sur la convention de nommage et vous ne pouvez pas spécifier singleton ou style de vie transitoire séparément.

https://blogs.msdn.microsoft.com/agile/2013/03/12/unity-configuration-registration-by-convention/

est-il un moyen de faire ce que vous pouvez faire au château de Windsor, comme dans l'exemple ci-dessus j'ai donné, sur la base des interfaces marqueurs?

+1

'je l'ai fait dans le château de windsor dans le passé, maintenant je veux le faire via l'unité .. . »- Pourquoi déménagez-vous d'un conteneur DI entièrement pris en charge à un conteneur * mort *? Unity n'est plus supporté (https://github.com/unitycontainer/unity/issues) et même quand c'était le cas, il était sérieusement en retard sur les fonctionnalités. Microsoft [a abandonné le support pour cela] (https://blogs.msdn.microsoft.com/dotnet/2015/08/21/the-future-of-unity/), mais les nouveaux propriétaires ne se soucient pas de le soutenir soit - il n'y a pas eu d'engagement depuis un an et demi. – NightOwl888

+0

+100 pour le commentaire de @ NightOwl888 :) – Steven

Répondre

0

Vu:

public interface ISingletonDependency { } 
public interface ITransientDependency { } 

public interface IPersonRepository : ISingletonDependency { } 
public class PersonRepository : IPersonRepository { } 

public interface IPersonService : ITransientDependency { } 
public class PersonService : IPersonService { } 

Ensuite, vous pouvez enregistrer les types en utilisant:

var container = new UnityContainer(); 

container.RegisterTypes(
    AllClasses.FromAssembliesInBasePath().Where(
     // Could also match on namespace etc. here 
     t => t.Assembly.GetName().Name.StartsWith("SolutionName")), 
    WithMappings.FromMatchingInterface, 
    WithName.Default, 
    WithLifetime.FromMarkerInterface); 

// Singleton 
Debug.Assert(ReferenceEquals(container.Resolve<IPersonRepository>(), container.Resolve<IPersonRepository>())); 

// Transient 
Debug.Assert(!ReferenceEquals(container.Resolve<IPersonService>(), container.Resolve<IPersonService>())); 

WithLifetime.FromMarkerInterface est une convention personnalisée qui utilise l'interface marqueur pour sélectionner le bon LifetimeManager:

public static class WithLifetime 
{ 
    public static LifetimeManager FromMarkerInterface(Type type) 
    { 
     if (typeof(ISingletonDependency).IsAssignableFrom(type)) 
     { 
      return new ContainerControlledLifetimeManager(); 
     } 

     return new TransientLifetimeManager(); 
    } 
} 

Dans ce cas tout est transitoire, à moins qu'il ne s'agisse d'un ISingletonDependency, mais vous pourriez rendre les règles plus explicites (par ex. lancer si aucune interface de marqueur valide n'est trouvée).

Si vous pouvez affiner votre clause where AllClasses.FromAssembliesInBasePath().Where alors vous pourriez probablement avec une seule ligne:

container.RegisterTypes(
AllClasses.FromAssembliesInBasePath().Where(
    t => t.Namespace.StartsWith("SolutionName.Repository") || 
     t.Namespace.StartsWith("SolutionName.Service")), 
    WithMappings.FromMatchingInterface, 
    WithName.Default, 
    WithLifetime.FromMarkerInterface);