Passing Func<bool> argument in constructor causing issue with Ninject - ninject

I am creating a factory using interface as
public interface ICommandFactory
{
ICommand CreateCommand(Action executeMethod);
ICommand CreateCommand(Action executeMethod, Func<bool> canExecuteMethod);
}
public class DelegateCommand : DelegateCommand<object>
{
public DelegateCommand(Action executeMethod)
: base(o => executeMethod())
{
}
public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod)
: base(o => executeMethod(), o => canExecuteMethod())
{
}
}
public class DelegateCommand<T> : ICommand
{
public DelegateCommand(Action<T> executeMethod)
: this(executeMethod, null)
{
}
public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
{
}
}
My Ninject binding is done using
_kernel.Bind(x => x.FromAssembliesMatching("xyz*")
.SelectAllClasses()
.BindAllInterfaces());
_kernel.Bind(x => x.FromAssembliesMatching("xyz*")
.SelectAllInterfaces()
.EndingWith("Factory")
.BindToFactory()
.Configure(c => c.InSingletonScope()));
When I call in my view model it is causing activation exception although I tried with Named binding.
public class MyViewModel
{
public ICommand SaveCommand {get; private set;}
public MyViewModel(ICommandFactory commandFactory)
{
SaveCommand = commandFactory.CreateCommand(Save, () => SelectedTask != null);
}
}
The exception is caused in DelegateCommand's constructor on 'o => canExecuteMethod()' line. Also, I cannot use constructor param passing in Ninject as my logic for canExecute is in my ViewModel. Any solution or fix is accepted.

Your issue is caused by Ninject.Extensions.Factory creating a binding for Func<>'s.
When you are using said extension, ninject is configured so that you can inject a Func<> as a factory. Func<bool> is basically bound like
kernel.Bind<Func<bool>>().ToMethod(() =>
{
return (Func<bool>) = () => kernel.Get<bool>();
}
Now this is paired with the fact, that ninject will use the public constructor with the most parameters it can resolve. That means, even if you use CreateCommand(Action executeMethod);, ninject will use the public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod) constructor and inject a "bool factory" as the Func<bool> parameter.
Workarounds
Wrapping the Func in an interface
There's many ways to do this, let me show you one:
public class Wrapper<T>
{
public T Wrapped { get; set; }
}
and adapt the factory to:
public interface ICommandFactory
{
ICommand CreateCommand(Action executeMethod, Wrapper<Func<bool>> canExecuteMethod);
}
and the delegate command constructor:
public class DelegateCommand : ICommand
{
public DelegateCommand(Action<T> executeMethod, Wrapper<Func<bool>> canExecuteMethod)
{
}
}
Removing the factory extensions Func bindings
See Stop Ninject from binding Func<T, T, bool> automatically

Related

Error activating service - Ninject

I am getting the following error whenever I try to inject one of my service's dependency into the MVC controller:
Error activating IFeedService No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IFeedService into parameter svc of constructor of type FeedController
1) Request for FeedController
Suggestions:
1) Ensure that you have defined a binding for IFeedService.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.
======================================================================
Here's how my code looks like:
ObjectFactory.cs
private static void RegisterServices(IKernel kernel)
{
// Contexts
kernel.Bind<IEntityObjectContext>().To<Entities>();
kernel.Bind<IAzureObjectContext>().To<AzureTableObjectContext>();
// Repositories
kernel.Bind<IEFRepository>().To<EFRepository>();
kernel.Bind<IAzureRepository>().To<AzureRepository>();
// Services
kernel.Bind<IFeedService>().To<FeedService>();
}
IEFRepository.cs
public interface IEFRepository : IDisposable
{
void SetContext(IEntityObjectContext context);
IQueryable<T> GetAll<T>() where T : class;
}
EFRepository.cs
public class EFRepository : IEFRepository
{
internal IEntityObjectContext context;
private Dictionary<Type, object> objectSets;
public EFRepository(IEntityObjectContext context)
{
this.context = context;
objectSets = new Dictionary<Type, object>();
}
public void SetContext(IEntityObjectContext context)
{
this.context = context;
}
}
IFeedService.cs
public interface IFeedService : IDisposable
{
IQueryable<FeedItem> GetPosts();
}
FeedService.cs
public class FeedService : IFeedService
{
private IEntityObjectContext _context;
private readonly IEFRepository _repo;
public FeedService(IEntityObjectContext context,
IEFRepository repo)
{
_context = context;
_repo = repo;
_repo.SetContext(_context);
}
public IQueryable<FeedItem> GetPosts()
{
using (_repo)
{
return _repo.GetAll<FeedItem>().Take(10);
}
}
}
FeedController.cs
public class FeedController : Controller
{
private readonly IFeedService _svc;
public FeedController(IFeedService svc)
{
_svc = svc;
}
}
As you can see, there are some nested dependency there in action. Not sure though, what needs to be added/removed for this bit to work.
Note: The error is thrown whenever I request the Feed/FetchFeed path. I also tried to comment out the FeedService's constructor portion to see if the nested dependencies are creating any problem, but again same error was thrown.
EDIT 1:
Rest of the code for the ObjectFactory.cs
class ObjectFactory
{
static ObjectFactory()
{
RegisterServices(kernel);
}
static IKernel kernel = new StandardKernel();
public static T GetInstance<T>()
{
return kernel.Get<T>();
}
private static void RegisterServices(IKernel kernel)
{
//...
}
}
EDIT 2:
I even tried to write a fairly basic service, but still the same error. Here's what I tried with:
public interface ITest
{
void CheckItOut();
}
public class Test : ITest
{
public void CheckItOut()
{
}
}
ObjectFactory.cs
kernel.Bind<ITest>().To<Test>();

Constructor parameter for injected class

Let's say I would like to inject an implementation of this interface:
interface IService { ... }
implemented as:
class MyService : IService
{
public MyService(string s) { }
}
in an instance of this class:
class Target
{
[Inject]
public IService { private get; set; }
}
I do the injection by calling kernel.Inject(new Target()), but what if I would like to specify the parameter s of the constructor depending on some context when calling Inject?
Is there a way to achieve such context-dependant service initialization at injection?
Thanks!
In most cases you should not use Field Injection, it should be
used only in rare cases of circular dependencies.
You should only use the kernel once at the start of your
application and never again.
Example Code:
interface IService { ... }
class Service : IService
{
public Service(string s) { ... }
}
interface ITarget { ... }
class Target : ITarget
{
private IService _service;
public Target(IServiceFactory serviceFactory, string s)
{
_service = serviceFactory.Create(s);
}
}
interface ITargetFactory
{
ITarget Create(string s);
}
interface IServiceFactory
{
IService Create(string s);
}
class NinjectBindModule : NinjectModule
{
public NinjectBindModule()
{
Bind<ITarget>().To<Target>();
Bind<IService>().To<Service>();
Bind<ITargetFactory>().ToFactory().InSingletonScope();
Bind<IServiceFactory>().ToFactory().InSingletonScope();
}
}
Usage:
public class Program
{
public static void Main(string[] args)
{
IKernel kernel = new StandardKernel(new NinjectBindModule());
var targetFactory = kernel.Get<ITargetFactory>();
var target = targetFactory.Create("myString");
target.DoStuff();
}
}
Simply done using parameters...
kernel.Inject(new Target(), new ConstructorArgument("s", "someString", true));

Is it possible to use one generic/abstract service in ServiceStack?

I am developing a (hopefully) RESTful API using ServiceStack.
I noticed that most of my services look the same, for example, a GET method will look something like this:
try
{
Validate();
GetData();
return Response();
}
catch (Exception)
{
//TODO: Log the exception
throw; //rethrow
}
lets say I got 20 resources, 20 request DTOs, so I got about 20 services of the same template more or less...
I tried to make a generic or abstract Service so I can create inheriting services which just implement the relevant behavior but I got stuck because the request DTOs weren't as needed for serialization.
Is there any way to do it?
EDIT:
an Example for what I'm trying to do:
public abstract class MyService<TResponse,TRequest> : Service
{
protected abstract TResponse InnerGet();
protected abstract void InnerDelete();
public TResponse Get(TRequest request)
{
//General Code Here.
TResponse response = InnerGet();
//General Code Here.
return response;
}
public void Delete(TRequest request)
{
//General Code Here.
InnerDelete();
//General Code Here.
}
}
public class AccountService : MyService<Accounts, Account>
{
protected override Accounts InnerGet()
{
throw new NotImplementedException();//Get the data from BL
}
protected override void InnerDelete()
{
throw new NotImplementedException();
}
}
To do this in the New API we've introduced the concept of a IServiceRunner that decouples the execution of your service from the implementation of it.
To add your own Service Hooks you just need to override the default Service Runner in your AppHost from its default implementation:
public virtual IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{
return new ServiceRunner<TRequest>(this, actionContext); //Cached per Service Action
}
With your own:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{
return new MyServiceRunner<TRequest>(this, actionContext); //Cached per Service Action
}
Where MyServiceRunner is just a custom class implementing the custom hooks you're interested in, e.g:
public class MyServiceRunner<T> : ServiceRunner<T> {
public override void OnBeforeExecute(IRequestContext requestContext, TRequest request) {
// Called just before any Action is executed
}
public override object OnAfterExecute(IRequestContext requestContext, object response) {
// Called just after any Action is executed, you can modify the response returned here as well
}
public override object HandleException(IRequestContext requestContext, TRequest request, Exception ex) {
// Called whenever an exception is thrown in your Services Action
}
}
Also for more fine-grained Error Handling options check out the Error Handling wiki page.
My solution was to add an additional layer where I can handle Logic per entity:
Base Logic Sample:
public interface IEntity
{
long Id { get; set; }
}
public interface IReadOnlyLogic<Entity> where Entity : class, IEntity
{
List<Entity> GetAll();
Entity GetById(long Id);
}
public abstract class ReadOnlyLogic<Entity> : IReadOnlyLogic<Entity> where Entity : class, IEntity, new()
{
public IDbConnection Db { get; set; }
#region HOOKS
protected SqlExpression<Entity> OnGetList(SqlExpression<Entity> query) { return query; }
protected SqlExpression<Entity> OnGetSingle(SqlExpression<Entity> query) { return OnGetList(query); }
#endregion
public List<Entity> GetAll()
{
var query = OnGetList(Db.From<Entity>());
return Db.Select(query);
}
public Entity GetById(long id)
{
var query = OnGetSingle(Db.From<Entity>())
.Where(e => e.Id == id);
var entity = Db.Single(query);
return entity;
}
}
Then we can use hooks like:
public interface IHello : IReadOnlyLogic<Hello> { }
public class HelloLogic : ReadOnlyLogic<Hello>, IHello
{
protected override SqlExpression<Hello> OnGetList(SqlExpression<Hello> query)
{
return query.Where(h => h.Name == "Something");
}
}
Finally our service only calls our logic:
public class MyServices : Service
{
IHello helloLogic;
public object Get()
{
return helloLogic.GetAll();
}
}

Ninject Several constructors have the same priority

I can't get rid of the exception which comes from Ninject "Several constructors have the same priority"
I have repository
public interface IRepository<TEntity> where TEntity : class
{
List<TEntity> FetchAll();
IQueryable<TEntity> Query { get; }
void Add(TEntity entity);
void Delete(TEntity entity);
void Save();
}
public class Repository<T> : IRepository<T> where T : class
{
private readonly DataContext _db;
public Repository(DataContext db)
{
_db = db;
}
#region IRepository<T> Members
public IQueryable<T> Query
{
get { return _db.GetTable<T>(); }
}
public List<T> FetchAll()
{
return Query.ToList();
}
public void Add(T entity)
{
_db.GetTable<T>().InsertOnSubmit(entity);
}
public void Delete(T entity)
{
_db.GetTable<T>().DeleteOnSubmit(entity);
}
public void Save()
{
_db.SubmitChanges();
}
#endregion
}
Controller where I am trying to bind repository
public class AdminController : Controller
{
private readonly IRepository<Store> _storeRepository;
public AdminController(IRepository<Store> storeRepository)
{
_storeRepository = storeRepository;
}
}
Ninject boot strapper
private static void RegisterServices(IKernel kernel)
{
var connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
kernel.Bind(typeof (DataContext)).ToMethod(context => new DataContext(connectionString));
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
}
After I run app I get error
Error activating DataContext using implicit self-binding of DataContext
Several constructors have the same priority. Please specify the constructor using ToConstructor syntax or add an Inject attribute.
Constructors:
DataContext(string fileOrServerOrConnectionMappingSource mapping)
DataContext(IDbConnection connectionMappingSource mapping)
It seems that Ninject tries to bind to DataContext class constructor
namespace System.Data.Linq: IDisposable
{
public class DataContext : IDisposable
{
public DataContext(IDbConnection connection);
public DataContext(string fileOrServerOrConnection);
//skip code
}
but I want to bind to my repository constructor
public class Repository<T> : IRepository<T> where T : class
{
private readonly DataContext _db;
public Repository(DataContext db)
{
_db = db;
}
//skip code
}
Also if I remove line below form boot strapper I still get the same exception. It seems Ninject automatically tries to bind dependencies when I am trying to bind Repository.
kernel.Bind(typeof (DataContext)).ToMethod(context => new DataContext(connectionString));

Overriding FluentNHibernate DefaultCascade for many types at once

I have an abstract entity base class defined like this:
public abstract class SessionItem : Entity
{
public virtual Session Session { get; set; }
}
In addition, I'm using auto mapping:
private AutoPersistenceModel CreateAutomappings()
{
return AutoMap
// configuration
.Conventions.Add(DefaultCascade.All())
// more configuration
}
SessionItem has several derived classes/tables, and I'd like to override the cascading policy for all of them. I tried the following:
public class SessionItemAutommapingOverride : IAutoMappingOverride<SessionItem>
{
public void Override(AutoMapping<SessionItem> mapping)
{
mapping.References(x => x.Session).Cascade.None();
}
}
But unfortunately the override is not called since SessionItem is abstract (and is not mapped). I prefer to avoid overriding it for each subclass (using IAutoMappingOverride).
Is there any way to override cascading for multiple types, without using IAutoMappingOverride<> for each one?
public class SessionReferenceCascadeNone : IReferenceConvention, IReferenceConventionAcceptance
{
public void Accept(IAcceptanceCriteria<IManyToOneInspector> criteria)
{
criteria.Expect(x =>
typeof(SessionItem).IsAssignableFrom(x.EntityType) &&
x.Property.PropertyType == typeof(Session));
}
public void Apply(IManyToOneInstance instance)
{
instance.Cascade.None();
}
}
Apparently this is possible by using IReferenceConvention:
public class CascadeNoneOverrideConvention : IReferenceConvention
{
public void Apply(IManyToOneInstance instance)
{
// override
}
}