Register null as instance in Unity container

前端 未结 5 1360
北恋
北恋 2020-12-17 10:08

I have a repository class with optional dependency:

class MyRepository : BaseRepository, IMyRepository
{
    public MyRepository(IDataContext dataContext, IC         


        
相关标签:
5条回答
  • 2020-12-17 10:47

    I found that RegisterType, instead of Register instance, supports returning null.

    container.RegisterType<IInterface>(new InjectionFactory((c) => null));
    

    This was the most straightforward way of getting an actual null to be returned.

    0 讨论(0)
  • 2020-12-17 11:01

    In the .RegisterType<IMyRepository, MyRepository>() call, specify the InjectionConstructor with an OptionalParameter, as in

    .RegisterType<IMyRepository, MyRepository>(new InjectionConstructor(
    new ResolvedParameter<IDataContext>(), 
    new OptionalParameter<ICacheProvider>()));
    
    0 讨论(0)
  • 2020-12-17 11:06

    For 'nice to have' dependencies you should use property injection instead of ctor injection. Config would look something like this:

    public class MyRepository
    {
      public ICacheProvider Cache { get; set; }
    }
    
    container.RegisterType<MyRepository>(new InjectionProperty("Cache", typeof(ICacheProvider)));
    

    That would inject an implementation of ICacheProvider into a property named Cache of your MyRepository. As you would have to implement null checks wherever you make a call to the Cache property inside your repository class I would go with @dtryon's proposal and implement a NullCacheProvider. That is far more convenient and less error prone.

    0 讨论(0)
  • 2020-12-17 11:06

    Simplest Non-Obsolete solution

    Calling RegisterType with an InjectionFactory is currently obsolete, so here is the currently recommended approach:

    container.RegisterFactory<ITypeToResolve>(c => null);
    

    Flexible Extension Method

    Or if you want to make an extension method to return anything you want you could do something like:

    public static void RegisterFactory<TToResolve>(IUnityContainer container, Func<TToResolve> factory) => 
            container.RegisterFactory<TToResolve>(c => factory.Invoke());
    

    Then to consume that you'd do:

    container.RegisterFactory<ITypeToResolve>(() => new MyTypeToResolve());
    
    0 讨论(0)
  • 2020-12-17 11:10

    I've ended with implementing some sort of a NullObject pattern on my optional dependency:

    public class NullCacheProvider : ICacheProvider
    {
        // …
    }
    

    And in the base repository class i have check:

    public class BaseRepository
    {
        protected readonly ICacheProvider CacheProvider;
        protected readonly bool ShouldUseCache;
    
        protected BaseRepository(IDataContext context, ICacheProvider cacheProvider)
        {
            CacheProvider = cacheProvider;
            ShouldUseCache = 
                CacheProvider != null && !(CacheProvider is NullCacheProvider);
        }
    }
    

    Then in a projects where i don't need a cache i have configured Unity like this:

    container
        .RegisterType<IDataContext, MyDataContext>(new PerResolveLifetimeManager(), new InjectionConstructor())
        .RegisterType<ICacheProvider, NullCacheProvider>() 
        .RegisterType<IMyRepository, MyRepository>();
    

    The point of all this is that the particular repository may act differently depending on fact of existence the optional dependency. It may seem as some architectural flaw but the solution meets my requirements.

    0 讨论(0)
提交回复
热议问题