Unity with the same interface, multiple factories

2019-08-05 17:57发布

So the issue, is when I declare:

[Dependency]
public AuthenticationService _authenticationServices { get; set; }

The _authenticationServices will constantly remain null. It isn't referenced, which will throw a Null Reference Exception. I'm assuming the issue stems from my Unity Configuration file:

container.RegisterType<ICrudFactory, ZNodeDataContextFactory>();
container.RegisterType<ICrudFactory, MincronDataContextFactory>();

Since they both use the same interface, but a separate concrete implementation. The implementation is as follows:

public interface ICrud : IDisposable
{
     // Method's to be exposed, via general repository.
}

public interface ICrudFactory
{
     ICrud Create();
}

public ZNodeDataContext : DbContext, ICrud
{
     // Concrete implementation.
}

public MincronDataContext : DbContext, ICrud
{
     // Concrete implementation.
}

public ZNodeDataContextFactory : ICrudFactory
{
     ICrud ICrudFactory.Create()
     {
           return ZNodeDataContext();
     }
}

public MincronDataContextFactory : ICrudFactory
{
     ICrud ICrudFactory.Create()
     {
           return MincronDataContext();
     }
}

public class AuthenticationService
{
     private readonly ICrudFactory _factory;
     public AuthenticationService(ICrudFactory factory)
     {
         _factory = factory;
     }

     public void Sample()
     {
          using(var context = _factory.Create())
              context.Method(...);
     }
}

I'd like to keep that structure, to avoid code duplication.

2条回答
Animai°情兽
2楼-- · 2019-08-05 18:29

I ended up solving the issue, by creating particular containers for each generic repository.

public interface IZNodeContextFactory : ICrudFactory
{

}

public interface IMincronContextFactory : ICrudFactory
{

}

By doing it in this manner, I was able to simply do:

container.RegisterType<IZNodeContextFactory, ZNodeContextFactory>();
container.RegisterType<IMincronContextFactory, MincronContextFactory>();

This allowed the automatic dependency resolver to work, and implement since they now had unique names.

查看更多
一夜七次
3楼-- · 2019-08-05 18:33

Do you want to inject ZNodeDataContextFactory into AuthenticationService ? A bit of the point with the injection is that the service should not now anything about the implementation. But if you really want a specific implementation you can create a named instance.

public class AuthenticationService
{
     private readonly ICrudFactory _factory;
     public AuthenticationService([Dependency("ZNodeData")] ICrudFactory factory)
     {
         _factory = factory;
     }
}

And in your configuration:

container.RegisterType<ICrudFactory, ZNodeDataContextFactory>("ZNodeData");
container.RegisterType<ICrudFactory, MincronDataContextFactory>("MincronData");

Alternatively:

    public class AuthenticationService
    {
         private readonly IEnumerable<ICrudFactory> _factories;
         public AuthenticationService(ICrudFactory[] factories)
         {
             // Now you got both...
             _factories = factories;
             var zNodeFactory = _factories.FirstOrDefault(x => x.Factory == ZNode);
         }
    }


    public interface ICrudFactory
    {
         ICrud Create();
         // Something to identify the type of data. Maybe an enum?
         FactoryType Factory {get;}
    }

public ZNodeDataContextFactory : ICrudFactory
{
     ICrud ICrudFactory.Create()
     {
           return ZNodeDataContext();
     }

     FactoryType ICrudFactory.Factory
     {
        {get {return FactoryType.ZNode;}
     }
}
查看更多
登录 后发表回答