How to do decorator with composition pattern in Autofac and Ninject - ninject

I want to make a 'decorator' for the IRepository. This decorator is also a 'composition' of multiple IRepository's. In code:
public interface IRepository { }
public class RepositoryFoo : IRepository { }
public class RepositoryBar : IRepository { }
public class RepositoryDuh : IRepository { }
public class RepositoryComposition : IRepository
{
public RepositoryComposition(IRepository master, IEnumerable<IRepository> slaves) { }
}
The RepositoryComposition will in some cases call both master and slaves and in some cases only the master.
I have made this setup work with both Autofac and Ninject, but I think the Ninject solution is not so good. So the question is, can this be done better? And how?
Here is my Autofac solution:
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<RepositoryFoo>().Named<IRepository>("master");
builder.RegisterType<RepositoryBar>().Named<IRepository>("slave");
builder.RegisterType<RepositoryDuh>().Named<IRepository>("slave");
builder.Register<IRepository>(f => new RepositoryComposition(
f.ResolveNamed<IRepository>("master"),
f.ResolveNamed<IEnumerable<IRepository>>("slave"))
);
Here is my Ninject solution:
Bind<RepositoryFoo>().ToSelf();
Bind<RepositoryBar>().ToSelf();
Bind<RepositoryDuh>().ToSelf();
Bind<IRepository>().To<RepositoryComposition>().
WithConstructorArgument("somethings", f => f.Kernel.Get<RepositoryFoo>()).
WithConstructorArgument("slaves", f => new IRepository[] {
f.Kernel.Get<RepositoryBar>(),
f.Kernel.Get<RepositoryDuh>()
});
I both cases I will resolve in the IRepository interface.

This is not an answer but is useful to know given the question: the registration is simple with Simple Injector
container.Register<IRepository, RepositoryFoo>();
container.RegisterAll<IRepository>(typeof(RepositoryBar), typeof(RepositoryDuh));
container.RegisterDecorator(
typeof(IRepository),
typeof(RepositoryComposition),
context => context.ImplementationType == typeof(RepositoryFoo));

Related

ASP.NET 5 Controller dependency injection of concrete class with no interface in to controller

Is it possible to use StructureMap to scan assemblies to be aware of concrete classes that do not implement interfaces? I am fairly new to StructureMap so not sure if this should be an obvious thing.
For context, below are the highlights of the classes I am working with. UserController depends on an instance of UserManager which depends on an instance of IUserRepository.
public interface IUserRepository { }
public class UserRepository { }
public class UserManager
{
public UserManager(IUserRepository repository) { }
}
public class UserController
{
public UserController(UserManager manager) { }
}
This is the code I have in my Startup.ConfigureServices method to do the scanning for DI:
// Setup dependencies using StructureMap
var container = new Container(x =>
{
x.Scan(s =>
{
s.AssemblyContainingType<UserRepository>();
s.WithDefaultConventions();
});
});
container.Populate(services);
The problem is I get the following error:
Unable to resolve service for type 'UserManager' while attempting to
activate 'UserController'.
If I add the following line to Startup.ConfigureServices then it works, but I am looking for a solution that doesn't require me to have a line for every manager. I have been thinking StructureMap assembly scanning could solve this but I am open to other solutions as well.
services.AddTransient<UserManager>();
Add .AddControllersAsServices() extention method to your services.AddMvc() call.
Result:
services.AddMvc().AddControllersAsServices();

Implement FluentSecurity 2.0.0 with Ninject MVC

Error activating ISecurityContext using binding from ISecurityContext to SecurityContext.
I'm getting the above error with FluentSecurity 2.0.0 when I'm trying to configure it with Ninject.Web.Mvc3 in an ASP.NET MVC 4 web application.
I think the internal IoC of FluentSecurity and the Ninject IoC may be clashing. Or I may be incorrectly setting up the DependencyResolver in the SecurityConfigurator.
I need to set it up with IoC as I need to get the UserRoles through an injected class.
public static class SecurityConfig
{
public static ISecurityConfiguration Configure()
{
SecurityConfigurator.Configure(
configuration =>
{
configuration.ResolveServicesUsing(
DependencyResolver.Current.GetServices,
DependencyResolver.Current.GetService);
configuration.DefaultPolicyViolationHandlerIs(() => new DefaultPolicyViolationHandler());
configuration.GetAuthenticationStatusFrom(
() => HttpContext.Current.User.Identity.IsAuthenticated);
configuration.GetRolesFrom(
() =>
((IPersonManager)DependencyResolver
.Current
.GetService(typeof(IPersonManager)))
.GetCurrentUserRoles());
configuration.ForAllControllers().DenyAnonymousAccess();
configuration.For<AdminController>().RequireAnyRole(Role.Administrator);
});
return SecurityConfiguration.Current;
}
}
Where am I going wrong? Is there another way I could achieve this?
I faced the same situation. It happened because Ninject throws an exception when cannot resolve a dependency. I solved it implementing my own ISecurityServiceLocator
public class FluentSecurityServiceLocator : ISecurityServiceLocator
{
public static IKernel Kernel { get; set; }
public object Resolve(Type typeToResolve)
{
return Kernel.TryGet(typeToResolve);
}
public IEnumerable<object> ResolveAll(Type typeToResolve)
{
if (!Kernel.GetBindings(typeToResolve).Any())
{
return new List<object>();
}
return Kernel.GetAll(typeToResolve);
}
}
I passed the kernel instance in my ninject configuration class
FluentSecurityServiceLocator.Kernel = kernel;
Hope this helps!
I'm not really familiar with Ninject but are you sure that DependencyResolver.Current.GetServices and DependencyResolver.Current.GetService won't throw an exception when FluentSecurity asks for something (like ISecurityContext) that is not registered with Ninject?
In structuremap there is a method called TryGetInstance that won't throw an exception when asking for something that is not registered in the container. You can read more on how FluentSecurity and IoC works here:
https://github.com/kristofferahl/FluentSecurity/wiki/IoC-container-integration

StructureMap, MVC and ObjectInstantiation

I am using StructureMap as DI with MVC 4. I am pushing certain objects in the constructor via StructureMap.
Following I have in the the bootstraper
public static void ConfigureDependencies()
{
ObjectFactory.Initialize(IE =>
{
IE.UseDefaultStructureMapConfigFile = true;
});
}
Controller Factory is as following
public class ControllerMyFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
return ObjectFactory.GetInstance(controllerType) as IController;
}
}
Then I am plugging this in Global.asax
BootStrapper.ConfigureDependencies();
ControllerBuilder.Current.SetControllerFactory(new ControllerMyFactory());
Following is one of my Controller
public class SomeController : Controller
{
ISomeService service;
public SomeController(ISomeService service)
{
this.service = service;
}
}
Now my problem is object Instantiation, which are being passed in the constructor.
I used to construct this object like Following
ISomeService service = CommonGateway.GetChannnel<ISomeService>();
How do I plugin this with StructureMap? How do I change the way StructureMap will instantiate the objects?
Please let me know if I am not very clear?
Thanks,
A
You just need to configure StructureMap to know about your ISomeService and how to instantiate it like this:
ObjectFactory.Initialize(IE =>
{
IE.For<ISomeService>().Use(() => CommonGateway.GetChannel<ISomeService>() as ISomeService);
});
This will then call your factory method when instantiating your controller, because your controller is already being created by StructureMap.

Ninject property binding, how to do correctly

I have installed Ninject (v4.0.30319) package in test project to test. Create test code below, unfortunately ValidateAbuse.Instance.Repository is always Null. Why Ninject do not bind repository to ValidateAbuse.Repository property?
Some of you may suggest to use constructor binding but I can't use it due to code structure. The below code is just example and I need to find a way to bind to property.
Test method which always fail
[TestMethod]
public void PropertyInjection()
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<ISettingsRepository>().To<SettingsRepository>();
Assert.IsNotNull(ValidateAbuse.Instance.Repository);
}
}
The repository interface
public interface ISettingsRepository
{
List<string> GetIpAbuseList();
List<string> GetSourceAbuseList();
}
The repository implementation
public class SettingsRepository : ISettingsRepository
{
public List<string> GetIpAbuseList()
{
return DataAccess.Instance.Abuses.Where(p => p.TypeId == 1).Select(p => p.Source).ToList();
}
public List<string> GetSourceAbuseList()
{
return DataAccess.Instance.Abuses.Where(p => p.TypeId == 2).Select(p => p.Source).ToList();
}
}
The class to which I am trying to bind repository
public class ValidateAbuse
{
[Inject]
public ISettingsRepository Repository { get; set; }
public static ValidateAbuse Instance = new ValidateAbuse();
}
Ninject will only bind properties on an object when it creates an instance of that object. Since you are creating the instance of ValidateAbuse rather than Ninject creating it, it won't know anything about it and therefore be unable to set the property values upon creation.
EDIT:
You should remove the static singleton from ValidateAbuse and allow Ninject to manage it as a singleton.
kernel.Bind<ValidateAbuse>().ToSelf().InSingletonScope();
Then when you ask Ninject to create any class that needs an instance of ValidateAbuse, it will always get the same instance.
It seems like you don't fully understand how Ninject works or how to implement it so I would suggest you read the wiki https://github.com/ninject/ninject/wiki/How-Injection-Works and follow some more basic examples before trying to wire it into an existing application.

Entity framework DbContext in wcf per call instance mode

I have a repository like this
public abstract class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected DbContext _dbContext;
public BaseRepository(DbContext dbContext)
{
_dbContext = dbContext;
}
public TEntity GetByKey(object keyValue)
{
// todo
}
}
and a concrete repository like this
public CustomerRepository : BaseRepository<Customer> , ICustomerRepository
{
public CustomerRepository(DbContext context) : base (context) { }
public Customer FindCustomerByKey(string key)
{
_dbContext.Set<Customer>().Find(key);
}
}
I have wcf service like this
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class CustomerSatisfactionService : ICustomerSatisfactionService
{
private ICustomerRepository _customerRepository;
private IHelpDeskRepository _helpdeskRepository;
public AccountService(ICustomerRepository customerRepository,IHelpdeskRepository helpdeskRepository)
{
_customerRepository = customerRepository;
_helpdeskRepository = helpdeskRepository;
}
public void DoSomethingUsingBothRepositories()
{
// start unit of work
// _customerRepository.DoSomething();
// _helpdeskRepository.DoSomething();
// commit unit of work
}
}
and I am using StructureMap for injecting DbContext instances like this
For<DbContext>().Use(() => new MyApplicationContext());
My problem is when a client calls the service, a new CustomerSatisfactionService instance is created, hence new instances of CustomerRepository and HelpdeskRepository are created but with different DbContexts.
I want to implement the unit of work pattern, but in the DoSomethingWithBothRepositories method, the two repositories have different DbContexts.
Is there any way to tell structure map to spin up a DbContext instance on a per call basis?
You must specify lifecycle for your DbContext so that only one instance is created per call. StructureMap doesn't contain build-in lifecycle management for per call WCF but you can find one implementation on this blog.
You need to implement UnitOfWork pattern so that same context is shared amongst entities. Take a look at http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx for a way to implement it.
I don't know if you need/want StructureMap to control the instantiation of dbcontext, have a look at this reply, UoW and UoW Factory setup dbcontext for the calls that need to be made in the repository.
EF ObjectContext, Service and Repository - Managing context lifetime.