i want to inject a list to my viewmodel constructor with the ServiceLocator
my viewmodel:
public class ShowEmployeeViewModel: ViewModelBase
{
private IList<IEmployee> _empl;
public ShowEmployeeViewModel(IList<IEmployee> emp)
{
this._empl = emp;
_empl.Add(new Employee() { empName = "foo", enpFunction = "bar" });
}
}
my servicelocator:
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
//register the interface against the class
SimpleIoc.Default.Register < IList < IEmployee >, List <Employee>>();
SimpleIoc.Default.Register<ShowEmployeeViewModel>();
}
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public ShowEmployeeViewModel ShowEmployee
{
get
{
return ServiceLocator.Current.GetInstance<ShowEmployeeViewModel>();
}
}
when i run this code i got an error:
"Cannot register: Multiple constructors found in List`1 but none marked with PreferredConstructor."
PS: i only got this error when i try to registre a list "IList" but when i register my interface like this:
SimpleIoc.Default.Register < IEmployee , Employee >();
it works fine, any idea how to register a list?
thanks in advance
Don't map the IList interface, use a factory for your ShowEmployeeViewModel class:
SimpleIoc.Default.Register(() => new ShowEmployeeViewModel(new List<IEmployee>()));
Related
I'd like to put in a base class a method in order not to repeat it in the inherited classes. There are interfaces for the base class and the inherited classes. Once I create a inherited class object I cannot use the base class method that I want to use. ¿What's wrong?
Thanks in advance.
public interface IRepository
{
string GetError(string LogNumber);
}
public class Repository : IRepository
{
public Repository()
{
}
public string GetError(string LogNumber)
{
return "The error is " + LogNumber;
}
}
public interface ICustomerRepository
{
// READ
List<Customer> ReadAll();
}
public class CustomerRepository : Repository, ICustomerRepository
{
public CustomerRepository() : base()
{
}
public List<Customer> ReadAll()
{
return fooFunction();
}
}
CustomerRepository myRepository = new CustomerRepository()
myRepository.
I think your code working fine. Please check below solution
public Form1()
{
InitializeComponent();
CustomerRepository myRepository = new CustomerRepository();
myRepository.GetError("string error");
}
public interface IRepository
{
string GetError(string LogNumber);
}
public class Repository : IRepository
{
public Repository()
{
}
public string GetError(string LogNumber)
{
return "The error is " + LogNumber;
}
}
public interface ICustomerRepository
{
// READ
List<Customer> ReadAll();
}
public class CustomerRepository : Repository, ICustomerRepository
{
public CustomerRepository() : base()
{
}
public List<Customer> ReadAll()
{
List<Customer> list;
return list = new List<Customer>();
}
}
public class Customer
{
}
Are you trying to put these statements outside the class? If yes, you should put them inside a method or preferably inside a main method.
Also, there is a semicolon missing at the end of the object initialization.
"CustomerRepository myRepository = new CustomerRepository();
myRepository."
Try correcting, you will be able to access the method from your base class.
I have modular WPF app. In each module I want have its own Messenger. Because I want send some messages inside module (without tokens).
First module:
namespace NS1
{
public class MainViewModel : ViewModelBase
{
public MainViewModel(IMessenger messenger) : base(messenger)
{
.......
}
}
public class Module1
{
Messenger Messenger1;
static Module1()
{
Messenger1 = new Messenger();
SimpleIoc.Default.Register<IMessenger>(() => Messenger1);
SimpleIoc.Default.Register<MainViewModel>();
}
}
}
And second module:
namespace NS2
{
public class MainViewModel : ViewModelBase
{
public MainViewModel(IMessenger messenger) : base(messenger)
{
.......
}
}
public class Module2
{
Messenger Messenger2;
static Module2()
{
Messenger2 = new Messenger();
SimpleIoc.Default.Register<IMessenger>(() => Messenger2);
SimpleIoc.Default.Register<MainViewModel>();
}
}
}
Of course i have error in line
SimpleIoc.Default.Register<IMessenger>(() => Messenger2);
How I can inject Messenger1 to MainViewModel in NS1 and Messenger2 to MainViewModel in NS2?
Or is there other way? Tokens are good, but I must be sure that in different modules are no same tokens!
You need to register each separate instance of the Messenger interface with a key inside the SimpleIoc.
To get hold of the correct instance you'll also need to use the same key.
So constructor injecting will not be possible I'm afraid... you'll need to use the GetInstance method.
Code example is as follows
IMessenger m1 = new Messenger();
IMessenger m2 = new Messenger();
SimpleIoc.Default.Register<IMessenger>(() => m1, "Msg1");
SimpleIoc.Default.Register<IMessenger>(() => m2, "Msg2");
var t = SimpleIoc.Default.GetInstance<IMessenger>("Msg1");
var s = SimpleIoc.Default.GetInstance<IMessenger>("Msg2");
I have an MVC 5 application that uses EF 6 and implements Repository pattern with dependency injection using the DI container Ninject. The connection string for the dbcontext is stored in the Web.config file which the EF Context properly finds. Everything works fine. Lately, I have a requirement that the connection to my DBContext need to be determined at runtime and connect to different databases (but with exactly the same structure). So, I need to change the sql connectionstring part from the entity connectionstring at run-time before the repository is instantiated. I would really appreciate some help in doing it. I am not a DI guru; know just enough Ninject to get my things going.
Here is my Repository Base Interface:
public interface IRepositoryBase<T> where T : class
{
void Add(T entity, string userGuid = "");
void Delete(T entity);
// ... removed other method signatures for brevity
}
My Repository base implementation:
public abstract class RepositoryBase<D, T> : IRepositoryBase<T>, IDisposable
where T : class
where D : DbContext, new()
{
private Guid? currUserGuid = null;
private D dataContext;
protected D DataContext
{
get
{
if (dataContext == null)
dataContext = new D();
return dataContext;
}
set { dataContext = value; }
}
public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate)
{
return DataContext.Set<T>().Where(predicate);
}
public virtual IQueryable<T> GetAll()
{
IQueryable<T> query = DataContext.Set<T>();
return query;
}
public virtual void Delete(T entity)
{
OperationStatus stat = TryDelete(entity);
}
// .... removed rest for brevity
}
Interface and implementation for concrete class:
public interface ICustomerRepository : IRepositoryBase<Customer>
{
Customer GetCustomerAndStatus( Guid custGuid );
}
public class CustomerRepository : RepositoryBase<PCDataEFContext, Customer>, ICustomerRepository
{
public Customer GetCustomerAndStatus( Guid custGuid )
{
return DataContext.Customers.Include( x => x.CustStatusType )
.SingleOrDefault( x => x.PKGuid == custGuid );
}
}
My Ninject dependency resolver:
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver()
{
kernel = new StandardKernel();
AddBindings();
}
public IKernel Kernel { get { return kernel; } }
private void AddBindings()
{
kernel.Bind<ICustomerRepository>().To<CustomerRepository>();
// ... other bindings are omitted for brevity
}
}
and finally, here is my Entity Framework generated DBContext:
public partial class PCDataEFContext : DbContext
{
public PCDataEFContext()
: base("name=PCDataEFContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Customer> Customers { get; set; }
}
All the above code works great! But as I said in the beginning, I don't know how to inject the connection string into my Repositorybase class at runtime so that I don't have to modify any of my inherited repositories (I have plenty of them). Someone please help.
Babu.
Could you do it like this?
public partial class PCDataEFContext : DbContext
{
public PCDataEFContext()
: base(Util.GetTheConnectionString())
{ }
}
public class MyDerivedContext : PCDataEFContext
{
public MyDerivedContext()
: base()
{ }
}
class Util
{
public static string GetTheConnectionString()
{
// return the correct name based on some logic...
return "name=PCDataEFContext";
}
}
Another way of doing it, could be in the RepositorBase class you defined, by altering the connectionstring after the creation of the dbcontext:
protected D DataContext
{
get
{
if (dataContext == null)
{
dataContext = new D();
dataContext.Database.Connection.ConnectionString = "the new connectionstring";
}
return dataContext;
}
set { dataContext = value; }
}
I can see that the constructor of the ViewModelLocator is executed first when my application starts, but how to make the constructors of my ViewModels run after that, because inside them I have a registering that I want to happen in the beggining of my app. The constructor of my CustomViewModel runs when I enter the View because of the binding. The binding is to a master class called CompositeViewModel that contains my viewModels.
CompositeViewModel:
class CompositeViewModel
{
public static CustomViewModel customViewModel { get; set; }
static CompositeViewModel()
{
customViewModel = new CustomViewModel();
}
}
Here is my ViewModelLocator
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<CustomViewModel>();
SimpleIoc.Default.Register<MainViewModel>();
}
public CustomViewModelTripTypeView
{
get
{
return ServiceLocator.Current.GetInstance<CustomViewModel>();
}
}
This is the code in my CustomViewModels constructor:
public CustomViewModel()
{
Messenger.Default.Register<ObservableCollection<MyType>>
(
this,
(action) => ReceiveMessage(action)
);
}
private void ReceiveMessage(ObservableCollection<MyType> action)
{
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
this.MyDataSource.Clear();
foreach (MyTypet mt in action)
{
this.MyDataSource.Add(mt);
}
});
}
There is an overloaded method for Register method with bool argument
SimpleIOC.Default.Register<MainViewModel>(true);
This statement will immediately create an instance of MainViewModel.
PagesCollection.ViewModel.PagePictureCommands.cs
namespace PagesCollection.ViewModel
{
public partial class PagePicturesViewModel : IPropertieCommands
{
private ICommand deleteAlbum;
public ICommand _CreateAlbum
{
get
{
if (createAlbum == null)
createAlbum = new Model.DelegateCommand(CreateAlbum, CanAdd);
return createAlbum;
}
}
}
}
PagesCollection.ViewModel.PagePicturesViewModel.cs
namespace PagesCollection.ViewModel
{
public partial class PagePicturesViewModel : IPictureMethods
{
public void CreateAlbum(object param)
{...}
}
}
I have one 2 interfaces and one class which divided on 2.Each one half of class has implemented some of those interfaces.But I have a very strange error.
('PagesCollection.ViewModel.PagePicturesViewModel' does not implement interface member 'PagesCollection.Model.IPropertieCommands._CreateAlbum.set')
Can u help me please?
What is it you don't understand, because the error message seems pretty descriptive:
PagesCollection.ViewModel.PagePicturesViewModel' does not implement
interface member
'PagesCollection.Model.IPropertieCommands._CreateAlbum.set
I suspect that the interface looks like:
public interface IPropertieCommands
{
ICommand _CreateAlbum { get; set; }
}
Which defines that you must have a setter on that property!
So just add a setter in your implementation:
public ICommand _CreateAlbum
{
get
{
if (createAlbum == null)
createAlbum = new Model.DelegateCommand(CreateAlbum, CanAdd);
return createAlbum;
}
set
{
createdAlbum = value; // or something else sensible!
}
}
It looks like your IPropertieCommands interface requires that the _CreateAlbum property has a setter - but you've only implemented a getter.
public interface IPropertieCommands
{
ICommand _CreateAlbum { get;}
}
If you don't want this property to have a setter (readonly), you can have your interface code like above.