Unity DI auto-registration from specific Assembly

冷暖自知 提交于 2021-02-07 20:29:05

问题


I'm trying to use the Unity Registration by Convention feature. I can't figure out how to register from specific assembly/project files with the file ending "Repository".

container.RegisterTypes(
       AllClasses.FromAssembliesInBasePath(),
       WithMappings.FromMatchingInterface,
       WithName.Default,
       WithLifetime.ContainerControlled);

I've found only this example from a MSDN blog ( https://blogs.msdn.microsoft.com/agile/2013/03/12/unity-configuration-registration-by-convention/ ) post and as I understand it, this will search through all projects/assemblies and will look for default naming convention files Class and IClass.

I have a project in my solution named CManager.Repository with repository files ending with *Repository. They are auto-registered.

Any hint or help?


回答1:


For auto-registration of unity it's better to separate the Interfacesand Repositories as folder in the repository project with proper naming convention.

If you have all repositories under single project then it's not needed to scan for all assemblies. This should register all repositories under project CManager.Repository

  public static class UnityConfig
   {
     public static void RegisterComponents()
      {
        var container = new UnityContainer();
        var repositoryAssembly = AppDomain.CurrentDomain.GetAssemblies()
            .First(a => a.FullName == "CManager.Repository, Version=X.X.X.X, Culture=neutral, PublicKeyToken=null"); 

        container.RegisterTypes(repositoryAssembly.GetTypes(),
            WithMappings.FromMatchingInterface,
            WithName.Default,
            WithLifetime.ContainerControlled);      

        container.RegisterType<ApplicationDbContext>(new PerResolveLifetimeManager());
       // ................ register other things is needed
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
     }
  } 

we have to register unity components on application startup, traditionally inside Global.asax.cs file. So put UnityConfig.cs file on startup project under App_Start folder.

public class MvcApplication : HttpApplication
{
    protected void Application_Start()
    {
        UnityConfig.RegisterComponents();
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);            
    }      
}

and make sure other projects are linked up with startup project.




回答2:


This works for me on a enterprise web-api that I have been working on for months now. It has an n-tier architecture with a data layer that has .cs files that end with 'Repository'. While I agree with the other post the Interfaces should be seperated, in my web-api they are not implemented in this way.

using System;
using System.Web.Http;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using Unity.WebApi;

namespace Blah.Endpoints.App_Start
{
    /// <summary>
    /// Specifies the Unity configuration for the main container.
    /// </summary>
    public static class UnityConfig
    {
        public static void RegisterComponents()
        {
            var container = new UnityContainer();

            // register all your components with the container here
            // it is NOT necessary to register your controllers
            RegisterTypes(container);
            // e.g. container.RegisterType<ITestService, TestService>();

            GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
        }

        #region Unity Container
        private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
        {
            var container = new UnityContainer();
            RegisterTypes(container);
            return container;
        });

        /// <summary>
        /// Gets the configured Unity container.
        /// </summary>
        public static IUnityContainer GetConfiguredContainer()
        {
            return container.Value;
        }
        #endregion

        /// <summary>Registers the type mappings with the Unity container.</summary>
        /// <param name="container">The unity container to configure.</param>
        /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to 
        /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
        public static void RegisterTypes(IUnityContainer container)
        {

            container.RegisterTypes(AllClasses.FromLoadedAssemblies(),
                WithMappings.FromMatchingInterface,
                WithName.Default,
                null,                //WithLifetime IF we want to change the lifetime aspect aka Singletons 
                null,//GetMembers,
                false
                );
        }


    }
}

This setup has usually works for my team. Sometimes we still get classes that throw unity errors for no apparent reason. For those we do something like this;

public class WcfServiceFactory : UnityServiceHostFactory
    {
        protected override void ConfigureContainer(IUnityContainer container)
        {
            //Attach hook for AOP attributes
            container.AddNewExtension<Interception>();

            // register all your components with the container here
            // container
            //    .RegisterType<IService1, Service1>()
            //    .RegisterType<DataContext>(new HierarchicalLifetimeManager());

            container.RegisterTypes(AllClasses.FromLoadedAssemblies(),
                WithMappings.FromMatchingInterface,
                WithName.Default,
                null,                //WithLifetime IF we want to change the lifetime aspect aka Singletons 
                GetMembers,
                false
                );

            container.RegisterType<IPaymentService, PaymentService>();
            container.RegisterType<IPaymentManager, PaymentManager>();
            container.RegisterType<IPaymentMethodRepository, PaymentMethodRepository>();
            container.RegisterType<IPaymentWithdrawScheduleRepository, PaymentWithdrawScheduleRepository>();
            container.RegisterType<IPaymentPreEnrollmentRepository, PaymentPreEnrollmentRepository>();
            container.RegisterType<ISharedLoanDataRepository<tblPaymentMethod>, SharedLoanDataRepository<tblPaymentMethod>>();
            container.RegisterType<ISharedLoanDataRepository<tblPaymentWithdrawSchedule>, SharedLoanDataRepository<tblPaymentWithdrawSchedule>>();
            container.RegisterType<IPaymentWithdrawScheduleOffSetTypeRepository, PaymentWithdrawScheduleOffSetTypeRepository>();
            container.RegisterType<IPaymentMethodTypeRepository, PaymentMethodTypeRepository>();
            container.RegisterType<IPaymentWithdrawScheduleFrequencyTypeRepository, PaymentWithdrawScheduleFrequencyTypeRepository>();
            container.RegisterType<IPaymentCustomerNotificationRepository, PaymentCustomerNotificationRepository>();
            container.RegisterType<ITraceLogger, TraceLogger>();
            container.RegisterType<IPaymentWithdrawScheduleCancelReasonRepository, PaymentWithdrawScheduleCancelReasonRepository>();
        }

        private IEnumerable<InjectionMember> GetMembers(Type type)
        {
            var list = new List<InjectionMember>();
            list.Add(new InterceptionBehavior<PolicyInjectionBehavior>(type.ToString()));
            list.Add(new Interceptor<InterfaceInterceptor>(type.ToString()));
            return list;
        }
    } 

I hope this helps

Regards.



来源:https://stackoverflow.com/questions/39498934/unity-di-auto-registration-from-specific-assembly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!