2017-07-13 8 views
1

ich mehrere Projekte in meiner Lösung haben:Register Schnittstelle in Unity Container basierend auf Marker-Schnittstelle in verschiedenen Lebenszeit

Core 
Repository 
Service 
WebAPi 

Meine Unity Registrierung ist auf WebAPI Project.

Was ich versuche zu erreichen ist etwas, was ich in Schloss Windsor in der Vergangenheit getan haben, jetzt will ich über Unity das tun: Registrieren Schnittstelle Konvention https://github.com/castleproject/Windsor/blob/master/docs/registering-components-by-conventions.md

Ich habe zwei Marker-Schnittstellen.

public interface ISingletonDependency{} 
public interface ITransientDependency{} 

Für die Klassen in meinem Repository oder Service I tun:

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

} 

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

In meiner Dienstklasse:

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

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

ich dies tun für alle meine Klassen in ähnlicher Weise für DI und während der Registrierung habe ich das gemacht:

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() 
); 

So muss ich das nicht für jeden einzelnen tun, ich habe Ansatz in Unity gesehen, aber es basiert auf der Namenskonvention und Sie können Singleton oder Transient Lifestyle nicht separat angeben.

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

Gibt es eine Möglichkeit zu tun, was Sie in Schloss Windsor, wie im obigen Beispiel tun können, ich gab, basierend auf Marker-Schnittstellen?

+1

'i in Castle windsor in Vergangenheit getan haben, jetzt möchte ich über Unity, das zu tun .. .' - Warum ziehen Sie von einem vollständig unterstützten DI-Container zu einem * toten * Container? Unity wird nicht mehr unterstützt (https://github.com/unitycontainer/unity/issues) und selbst wenn es war, war es in Features sehr weit zurück. Microsoft [gab den Support dafür auf] (https://blogs.msdn.microsoft.com/dotnet/2015/08/21/the-future-of-unity/), aber die neuen Besitzer kümmern sich nicht darum, es zu unterstützen entweder - seit anderthalb Jahren gab es kein Commit mehr. – NightOwl888

+0

+100 für @ NightOwl888's Kommentar :) – Steven

Antwort

0

Gegeben:

public interface ISingletonDependency { } 
public interface ITransientDependency { } 

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

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

Dann könnten Sie mit dem Typen registrieren:

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 ist eine eigene Konvention, die die Marker-Schnittstelle verwendet die richtige LifetimeManager zu wählen:

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

     return new TransientLifetimeManager(); 
    } 
} 

In diesem Fall ist alles vorübergehend, es sei denn, es ist ein ISingletonDependency, aber Sie könnten die Regeln expliziter machen (z.B. wenn keine gültige Markerschnittstelle gefunden wird).

Wenn Sie könnten verengen Ihre where-Klausel in AllClasses.FromAssembliesInBasePath().Where dann könnte man wahrscheinlich mit einem Einzeiler weg:

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