I'm working on project who has a lot of common repeated functions in differents razor components doing same work. Like this.
void TrySelect(clsCity item)
{
_isOpen = false;
SelectedText = item.Nombre;
SelectedValue = item.ID;
objSearchHotel.SearchObject = item;
this.StateHasChanged();
}
example files
This function (and others) are used at least in 26 files. Im new into a pattern designs, it's possible to create a file as service and consume/inject that service with this "common functions" in every razor component that i need? Something like repository pattern?
i'm new on pattern designs, still learning and i can't understand at all
I will try to give an example of how it works in the form of your own codes.
Firstly, you should create an interface as follows:
public interface IFoo
{
public clsCity GetItem();
}
Now, you should create a service and inherit from above interface:
public class FooService:IFoo
{
public clsCity GetItem()
{
return clsCity;
}
}
You should register the interface and service in the startup as follows:
Services.AddScoped<IFoo,FooService>();
Finally, You can inject the FooService in any components as follows:
#inherits OwningComponentBase<IFoo>
.
.
<EditForm Model="clsCityModel">
<InputSelect #bind-Value=clsCityModel.Id>
clsCityModel.Nombre
</InputSelect>
</EditForm>
.
.
#code
{
private IFoo fooService => Service;
private clsCity clsCityModel = new clsCity();
protected override void OnInitialized()
{
base.OnInitialized();
TrySelect();
}
void TrySelect()
{
_isOpen = false;
clsCity clsCityModel = FooService.GetItem();
}
}
So, I would not suggest creating a base class and then inherit its funcionalities. If doing so, it should be an interface at least.
The best way to solve your issue from my point of view —- is to create a service too. You could create an app-scoped service that you can inject in any class you need.
Create an interface for the service
Create a service class inherited from the interface
Register the service
Inject it where you need
No more duplication
Useful link with instructions
I hope it helps you!
Related
I want to take advantage of dependency injection in my Xamarin project but can't get constructor injection to work in C# classes behind XAML views. Is there any way to do it ?
I've seen guides how to setup dependency injections in View Models, to later use them as repositories but that doesn't work for me.
So far I tried Ninject and Unity.
Code:
This is the service I want to use inside of my PCL project:
public class MyService : IMyService
{
public void Add(string myNote)
{
//Add Note logic
}
}
Interface:
public interface IMyService
{
void Add(string myNote);
}
Unity setup in App.Xaml:
public App ()
{
InitializeComponent();
var unityContainer = new UnityContainer();
unityContainer.RegisterType<IMyService, MyService>();
var unityServiceLocator = new UnityServiceLocator(unityContainer);
ServiceLocator.SetLocatorProvider(() => unityServiceLocator);
MainPage = new MainMasterMenu(); //<-- feel that I'm missing something here as I shouldn't be creating class instances with DI, right ?
}
Usage that I'd like to see. This is .CS file behind a XAML starting page:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainMasterMenu : MasterDetailPage
{
private IMyService _myService;
public MainMasterMenu(IMyService myService)
{
_myService = myService
}
private void SomeFormControlClickEvent(object sender, ItemChangedEventArgs e)
{
_myService.Add("hi");
}
}
For that simple example creating the MainMasterMenu directly would be no issue, but you would have to pass the reference to your service
MainPage = new MainMasterMenu(unityContainer.Resolve<IMyService>());
But this would mean that you'll have to change that line every time the constructor of MainMasterMenu changes. You could circumvent this by registering the MainMasterMenu, too.
unityContainer.RegisterType<MainMasterMenu>();
...
MainPage = unityContainer.Resolve<MainMasterPage>();
Anyway, anytime you want to navigate to another page, which needs any dependency registered with unity, you'll have to make sure to resolve its dependencies properly, which requires (at least indirect) access to the unity container. You could pass a wrapper that encapsules the access to unity
interface IPageResolver
{
T ResolvePage<T>()
where T : Page;
}
and then implement that resolver with unity
public class UnityPageResolver
{
private IUnityContainer unityContainer;
public UnityPageResolver(IUnityContainer unityContainer)
{
this.unityContainer = unityContainer;
}
public T ResolvePage<T>()
where T : Page // do we need this restriction here?
{
return unityContainer.Resolve<T>();
}
}
This gets registered with unity
unityContainer.RegisterInstance<IUnityContainer>(this);
unityContainer.RegisterType<IPageResolver, UnityPageResolver>();
But you should have a look at the Prism library (see here) that solves many of the issues (e.g. it provides an INavigationService that lets you navigate to other pages without caring about the dependencies and it provides facilities to resolve viewmodels automatically, including dependencies).
I'm new in AutoFac and I'm come across two problems that I need to implement in my WPF project using MVVM. I'm using an interface to implement a repository, but I'm going to implement multiple repositories for SQL, XML, and CSV. So my interface has this:
public interface IRepository<T> : IReadOnlyRepository<T>, IWriteOnlyRepository<T>
{
}
// covariance interface
public interface IReadOnlyRepository<out T> : IDisposable
{
T FindById(int id);
IEnumerable<T> GetAllRecords();
}
// contravariance interface
public interface IWriteOnlyRepository<in T> : IDisposable
{
void Add(T item);
void Delete(T item);
int Save();
}
public class SQLRepository<T> : IRepository<T>
{
// implements the interface using Entity Framework
}
public class XMLRepository<T> : IRepository<T>
{
// implements the interface using XML Serializer/Deserializer
}
public class CSVRepository<T> : IRepository<T>
{
// Implements the interface for TextReader/TextWriter for CSV Files (Excel)
}
So here's the rub: I was told by the boss that the customer needs to change repositories while still running the program. So I need to dynamically change the repository at run time. The default will be SQL Server, but the client may want to change to XML... WITHOUT losing the data that is already in the repository. The reason behind it is that if they load a configuration from SQL but they want to save it to a XML file and send it to their client, they can do so
-- OR --
They get an XML file from one of their clients, and they want to save the configuration to SQL, they can do so without worrying about re-entering the data.
I solved one problem by using Generics because I'll be using the same POCO data model class and therefore it preserves the data but then:
How do I implement the 3 different concrete repository classes?
How do I pass in the parameter of T?
I thought about using "named services" to differentiate between the concrete repository classes, and a model base class. I then would use a bootstrapper to look like this:
public class BootStrapper
{
public IContainer BootStrap()
{
var builder = new ContainerBuilder();
builder.RegisterType<MainWindow>.AsSelf();
builder.RegisterType<MainViewModel>.As<IMainViewModel>();
//?? How do I resolve T of IRepository<T>?
builder.RegisterType<SQLRepository>.Named<IRepository>("SQL")
builder.RegisterType<XMLRepository>.Named<IRepository>("XML")
builder.RegisterType<CSVRepository>.Named<IRepository>("CSV")
return builder.Build();
}
}
public partial class App : Application
{
protected override void OnStartUp(StartUpEventArgs e)
{
base.OnStartUp(e);
var bootsrapper = new BootStrapper();
var container = bootstrapper.BootStrap();
// ?? How do I set the SQLRepository as default?
var mainWindow = container.Resolve<MainWindow>();
mainWindow.Show();
}
}
Any suggestions?
EDIT: I forgot to add in there that I'm using Dependency Injection on my ViewModels, so therefore, in my MainViewModel:
public class MainViewModel
{
private IRepository<Model> _repository;
public MainViewModel(IRepository<Model> repo)
{
_repository = _repo;
}
}
now I did try as suggested that I change the code to this:
builder.RegisterGeneric(typeof(SQLRepository<>).As(typeof(IRepository<>));
builder.RegisterGeneric(typeof(XMLRepository<>).As(typeof(IRepository<>));
I then debug the code by stepping into it, and when I hit at MainViewModel constructor, it's giving me XMLRepository class. From what I've read in the documentation for "default registrations", it will always be XMLRepository and never SQLRepository. I then tried to "open generic decorator registration" like:
builder.RegisterGeneric(typeof(SQLRepository<>).Named("SQL", typeof(IRepository<>));
builder.RegisterGeneric(typeof(XMLRepository<>).Named("XML", typeof(IRepository<>));
builder.RegisterGenericDecorator(typeof(SQLRepository<>), typeof(IRepository<>), fromKey: "SQL");
builder.RegisterGenericDecorator(typeof(XMLRepository<>), typeof(IRepository<>), fromKey: "XML");
But then how do I resolve it when I'm trying to use the MainWindow?
UPDATE EDIT #2
Okay, so I was asked by a legitimate question by tdragon about how I wanted this resolved. The MainWindow.xaml.cs file looks like this:
public partial class MainWindow : Window
{
private MainViewModel _viewModel;
public MainWindow(MainViewModel viewModel)
{
InitializeComponent();
_viewModel = viewModel;
DataContext = _viewModel;
}
}
But the real problem is with the App.xaml.cs file, which I've already gave the code in the in my original question.
There is a Good article here in autofac documentation.
Use the RegisterGeneric() builder method to register generic components as below.
var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(SQLRepository<>));
builder.RegisterGeneric(typeof(XMLRepository<>));
builder.RegisterGeneric(typeof(CSVRepository<>));
builder.RegisterGeneric(typeof(SQLRepository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(XMLRepository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(CSVRepository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
builder.Register(c => new Myclass()).OnActivating(
e =>
{
e.Instance.SqlTaskRepo = e.Context.Resolve<SQLRepository<Task>>();
}
);
UPDATED
You can resolve T by scanning assembly instead that would be better way to resolve kindly take a look below code hope it will help you
builder.RegisterGeneric(typeof(SQLRepository<>));
builder.RegisterGeneric(typeof(XMLRepository<>));
builder.RegisterGeneric(typeof(CSVRepository<>));
var dataAccess = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(dataAccess)
.Where(t => typeof(SQLRepository<>).IsAssignableFrom(t));
builder.RegisterAssemblyTypes(dataAccess)
.Where(t => typeof(XMLRepository<>).IsAssignableFrom(t));
builder.RegisterAssemblyTypes(dataAccess)
.Where(t => typeof(CSVRepository<>).IsAssignableFrom(t));
builder.RegisterType<MainViewModel>();
One of possible solution would be to register your repositories using keys, instead of names:
var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(SqlRepository<>)).Keyed(RepositoryType.Sql, typeof(IRepository<>));
builder.RegisterGeneric(typeof(XmlRepository<>)).Keyed(RepositoryType.Xml, typeof(IRepository<>));
builder.RegisterGeneric(typeof(CsvRepository<>)).Keyed(RepositoryType.Csv, typeof(IRepository<>));
where keys would be some enum values (string could be used as well, but imho enum is cleaner and less error-prone), e.g.
enum RepositoryType { Sql, Xml, Csv }
Then, instead of injecting IRepository<Model> which always gives you latest registered dependency, you can inject IIndex<RepositoryType, IRepository<Model>>. Using index operator you can get proper repository type. In addition, you can implement some kind of ConfigurationProvider, where you can store currently selected type of repository, like:
public interface IConfigurationProvider
{
RepositoryType SelectedRepositoryType { get; set; }
}
public class ConfigurationProvider : IConfigurationProvider
{
public RepositoryType SelectedRepositoryType
{
get { /* read the value from some configuration file */ }
set { /* store the new value */ }
}
}
Of course, it should be also registered in the container. You can store this value wherever you want (app.config, any other custom file).
Then, the constructor of MainViewModel would look like this:
public MainViewModel(
IIndex<RepositoryType, IRepository<Model>> repoIndex,
IConfigurationProvider configurationProvider)
{
var repository = repoIndex[configurationProvider.SelectedRepositoryType]; // would return the repository of currently selected type
}
You can find more details about IIndex in Autofac documentation.
I have to admit, I was a bit floored when I got this answer. I'm posting this answer for anyone else that might have the same problem I've was facing.
Since the solution that was provided to me didn't work right (until tdragon updated his answer), I went to Googlegroups for Autofac and someone else came up with the answer.
However, I have given the credit to tdragon (thanks dude!) for coming up with the IIndex method which is why I put his post as an answer, but I gotten more feedback about it from other sources which is why I'm posting my answer.
I went and contacted Thomas Claudius Huber, the author of two great Pluralsight courses on WPF and MVVM. One was on doing ModelWrappers, and the other was doing unit testing with ViewModels. I strongly suggest those courses to newbies that are trying to refine their WPF and MVVM skills. It was his courses that got me turned on Autofac and it help out tremendously. Thomas and tdragon's solution using IIndexing did help resolve the problem.
But there is an interesting alternative that someone on the Autofac Googlegroup by Alex Meyer-Gleaves. His first alternative was using a Lambda expression which was:
builder.Register(c => new MainViewModel(c.ResolveNamed<IRepository<Stock>>("XMLrepository"), c.ResolveNamed<IRepository<Vendor>>("SQLRepository"))).AsSelf();
But he also mentioned that starting with Autofac 4.3.0, there was an attribute filter that will help with the issue. First thing I needed to do was add ".WithAttributeFiltering()" when building the container like this:
public IContainer BootStrap()
{
builder.RegisterType<MainViewModel>().AsSelf().WithAttributeFiltering();
builder.RegisterType<MainView>().AsSelf();
builder.RegisterGeneric(typeof(XMLRepository<>)).Keyed("XMLRepository", typeof(IRepository<>));
builder.RegisterGeneric(typeof(SQLRepository<>)).Keyed("SQLRepository", typeof(IRepository<>));
return builder.Build();
}
Then in the constructor, you can do this:
public MainViewModel([KeyFilter("XMLRepository")]IRepository<Stock> stockRepo,
[KeyFilter("XMLRepository")]IRepository<Vendor> vendorRepo)
{ ... // code here }
Thanks guys for all your help!
I am just starting to learn Dependency Injection and I am stuck here.
My project has a WCF DataService over an Entity Framework DbContext.
public class MyDataService : DataService<MyDbContext>
{
protected override MyDbContext CreateDataSource()
{
// I want to use dependency injection for this
return new MyDbContext();
}
}
The class is either
a) IIS hosted, so I don't have any control
b) for integration tests, created with var host = new DataServiceHost(type, new Uri[] { });
both use different contstructors for MyDbContext
So basically to inject the Context with this
protected override MyDbContext CreateDataSource()
{
INinjectModule module = ???; // -
IKernel kernel = new StandardKernel(module);
return kernel.Get<MyDbContext>();
}
So the question is, what is best practice in this situation?
Should I:
a) Create a Module in a Class Library that both main projects and the service use
b) Create a public static Variable inside the DataService project that holds the Ninject module.
c) Create a public static Variable inside the DataService project that holds the Ninject kernel
d) Something else.
I would prefer something like
protected override MyDbContext CreateDataSource()
{
DefaultKernel.Get<MyDbContext>();
}
Firstly, you should have a Composition Root. That is, a single place where your Kernel is created (not in every single function).
Secondly, you don't need a NinjectModule here.. you're asking Ninject to create an instance of a concrete object (which in almost all circumstances.. defeats the purpose).
What you should create, is a separate NinjectModule pass it into the constructor of the Kernel.. something like this:
interface IContext {
}
class MyDbContext : DbContext, IContext {
}
class YourModule : NinjectModule {
protected override void Bind() {
Bind<IContext>().To<MyDbContext>();
}
}
// In your composition root somewhere
var kernel = new StandardKernel(new NinjectModule[] { new YourModule() });
// in your createdatasource method
kernel.Get<IContext>();
This will get you started. Normally, your composition root is what drives injection of objects throughout your application, thereby eliminating the need to pass the Kernel around (which you will have to do in your current setup).
The hard thing to understand when starting out with DI/IoC is that it is the container's job to create your entire dependency graph. Therefore, if you setup the following bindings:
IContract1 -> ConcreteObject1
IContract2 -> ConcreteObject2
IContract3 -> ConcreteObject3
..and have the following setup:
class ConcreteObject1 : IContract1 {
public ConcreteObject1(IContract2 contract3) {
}
}
class ConcreteObject2 : IContract2 {
public ConcreteObject2(IContract3 contract3) {
}
}
If you ask your container for a concrete implementation of IContract1 (which will be ConcreteObject1), then it will create it.... BUT: ConcreteObject1 requires a concrete implementation of IContract2 in the constructor. So the container says "Wait, I know how to create this".. and passes in an instance of ConcreteObject2. Again, it says "wait, ConcreteObject2 wants a concrete implementation of IContract3.. again, it goes and fetches one.
Hopefully that helps.
I have been helping a few friends on a project and there is a class that uses Ninject. I am fairly new to C# and I have no idea what that class is doing, which is why I need to understand Ninject. Can anyone explain what Ninject is and when does one use it(with example if possible)? Or if you can point to some links that would be great too.
I tried this question: Ninject tutorials/documentations? but it didn't really help a beginner like me.
Ninject is dependency injector for .NET, practical realisation of pattern Dependency Injection (form of Inversion of Control pattern).
Suppose you have two classes DbRepository and Controller:
class Controller {
private DbRepository _repository;
// ... some methods that uses _repository
}
class DbRepository {
// ... some bussiness logic here ...
}
So, now you have two problems:
You must initialize _repository to use it. You have several options for doing this:
Manually, within the constructor. But what if the constructor of DbRepository changes? You would need to rewrite your Controller class because code it's dependent upon was changed. It's not hard if you have only one Controller, but if you have a couple of classes that have a dependency on your Repository you have a real problem.
You can use a service locator or factory. But now you have a dependency on your service locator. You have a global service locator and all code must use it. How you will you change the behavior of your service locator when you need to use it in one part of your code for activation logic but for something else in another part of your code? There is only one way - passing the service locator through constructors. But with more and more classes you will need to pass it more and more times. Anyway, it's a good thought but in the long run, it's a bad idea.
class Controller {
private DbRepository _repository;
public Controller() {
_repository = GlobalServiceLocator.Get<DbRepository>()
}
// ... some methods that uses _repository
}
You can use dependency injection. Look at the code:
class Controller {
private IRepository _repository;
public Controller(IRepository repository) {
_repository = repository;
}
}
Now when you need your controller you write: ninjectDevKernel.Get<Controller>(); or ninjectTestKernel.Get<Controller>();. You can switch beetween dependency resolvers as fast as you want. See? It's simple, you don't need to write a lot.
You can't create unit tests for it. Your Controller has a dependency on DbRepository and if you want to test some method that uses repository, your code will go to the database and ask it for data. That's slow, very slow. If your code in DbRepository changes, your unit test on Controller will fall. Only integration test must warn you of 'problems' in this case. What you need in unit tests - is to isolate your classes and test only one class in one test (in ideal - only one method). If your DbRepository code fails, you will think that Controller code failed - and that's bad (even if you have tests for DbRepository and Controller - they both will fail and you can start from the wrong place). It takes a lot of time to determine where the error really is. You need to know that class A is ok, and it was class B where something failed.
When you want to replace DbRepository with something else in all your classes, you have to do a lot of work.
You can't easily control the lifetime of DbRepository. An object of this class is created on initialization of Controller and deleted when Controller is deleted. There is no sharing between different instances of the Controller class and there is no sharing between other classes. With Ninject you can simply write:
kernel.Bind<IRepository>().To<DbRepository>().InSingletonScope();
A special feature of dependency injection - agile development! You describe that your controller uses a repository with interface IRepository. You don't need to write DbRepository, you can simply create a MemoryRepository class and develop Controller while another person develops DbRepository. When work on DbRepository is finished, you just rebind in your dependency resolver that default IRepository is now DbRepository. Have a lot of controllers? All of them will now use DbRepository. That's cool.
Read more:
Inversion of control (wiki)
Dependency injection (wiki)
Inversion of Control Containers and the Dependency Injection pattern (Martin Fowler)
Ninject is an Inversion of Control container.
What does it do?
Suppose you have a Car class that depends on a Driver class.
public class Car
{
public Car(IDriver driver)
{
///
}
}
In order to use the Car class you build it like so:
IDriver driver = new Driver();
var car = new Car(driver);
A IoC containter centralizes the knowledge about how to build classes. It is a central repository that knows a few things. For example, it knows that the concrete class that you need to use to build a car is a Driver and not any other IDriver.
For example, if you are developing a MVC application, you can tell Ninject how to build your controllers. You do so by registering which concrete classes satisfy specific interfaces. At run time Ninject will figure out which classes are needed to build the required controller, and all behind the scenes.
// Syntax for binding
Bind<IDriver>().To<Driver>();
This is beneficial because it lets you build systems that are more easily unit testable. Suppose that Driver encapsulates all database access for Car. In a unit test for Car you can do this:
IDriver driver = new TestDriver(); // a fake driver that does not go to the db
var car = new Car(driver);
There are entire frameworks that take care of automatically creating testing classes for you and they are called mocking frameworks.
For more information:
GitHub/Ninject Home
Inversion of Control
Inversion of Control Containers and the Dependency Injection pattern
Mock Object
Other answers are great but I would also like to point out this Implementing Dependency Injection using Ninject article.
This is one of the best articles I ever read which explains Dependency Injection and Ninject with a very elegant example.
Here's the snippet from the article:
Below Interface will be implemented by our (SMSService) and (MockSMSService), basically the new Interface (ISMSService) will expose the same behaviors of both services as the code below:
public interface ISMSService
{
void SendSMS(string phoneNumber, string body);
}
(SMSService) implementation to implement the (ISMSService) interface:
public class SMSService : ISMSService
{
public void SendSMS(string mobileNumber, string body)
{
SendSMSUsingGateway(mobileNumber, body);
}
private void SendSMSUsingGateway(string mobileNumber, string body)
{
/*implementation for sending SMS using gateway*/
Console.WriteLine("Sending SMS using gateway to mobile:
{0}. SMS body: {1}", mobileNumber, body);
}
}
(MockSMSService) with totally different implementation using the same interface:
public class MockSMSService :ISMSService
{
public void SendSMS(string phoneNumber, string body)
{
SaveSMSToFile(phoneNumber,body);
}
private void SaveSMSToFile(string mobileNumber, string body)
{
/*implementation for saving SMS to a file*/
Console.WriteLine("Mocking SMS using file to mobile:
{0}. SMS body: {1}", mobileNumber, body);
}
}
we need to implement a change to our (UIHandler) class constructor to pass the dependency through it, by doing this, the code which uses the (UIHandler) can determine which concrete implementation of (ISMSService) to use:
public class UIHandler
{
private readonly ISMSService _SMSService;
public UIHandler(ISMSService SMSService)
{
_SMSService = SMSService;
}
public void SendConfirmationMsg(string mobileNumber) {
_SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
}
}
Now, we have to create a separate class (NinjectBindings) which inherits from (NinjectModule). This class will be responsible to resolve dependencies at run time, then we’ll override the load event which is used to configure the binding in it. The nice thing about Ninject is that we do not need to change our code in (ISMSService), (SMSService), and (MockSMSService).
public class NinjectBindings : Ninject.Modules.NinjectModule
{
public override void Load()
{
Bind<ISMSService>().To<MockSMSService>();
}
}
Now in UI form code, we’ll use the binding for Ninject which will determine which implementation to use:
class Program
{
static void Main(string[] args)
{
IKernel _Kernal = new StandardKernel();
_Kernal.Load(Assembly.GetExecutingAssembly());
ISMSService _SMSService = _Kernal.Get<ISMSService>();
UIHandler _UIHandler = new UIHandler(_SMSService);
_UIHandler.SendConfirmationMsg("96279544480");
Console.ReadLine();
}
}
Now the code is using the Ninject Kernal to resolve all chain of dependencies, if we want to use the real service (SMSService) in Release mode (on production environment) instead of the mock one, we need to change on the Ninject binding class (NinjectBindings) only to use the right implementation or by using the #if DEBUG directive as below:
public class NinjectBindings : Ninject.Modules.NinjectModule
{
public override void Load()
{
#if DEBUG
Bind<ISMSService>().To<MockSMSService>();
#else
Bind<ISMSService>().To<SMSService>();
#endif
}
}
Now our binding class (NinjectBindings) is living on the top of all our execution code and we can control the configuration easily in once place.
Also, see What is Inversion of Control? some very simple examples are mentioned to understand IoC.
You have to understand the Dependency Injection(DI) first. Notice here,
public interface IService
{
void Serve();
}
public class Service1 : IService
{
public void Serve() {
Console.WriteLine("Service1 Called");
}
}
public class Service2 : IService
{
public void Serve() {
Console.WriteLine("Service2 Called");
}
}
public class Service3 : IService
{
public void Serve() {
Console.WriteLine("Service3 Called");
}
}
public class Client
{
private IService service;
public Client(IService _service) //Constructor injection
{
service = _service;
}
public void ServeMethod() {
service.Serve(); //Notice here, this Serve() method has no idea what to do.
} // runtime will assign the object, that is Ninject
}
class Program
{
static void Main(string[] args)
{
IService s1 = new Service1(); //N.B. Ninject assigns object with interface
Client c1 = new Client(s1);
c1.ServeMethod();
IService s2 = new Service2(); //N.B. Ninject assigns object with interface
c1 = new Client(s2);
c1.ServeMethod();
IService s3 = new Service3(); //N.B. Ninject assigns object with interface
c1 = new Client(s3);
c1.ServeMethod();
Console.ReadKey();
}
}
// Ninject creates object in runtime for interface in runtime in ASP.NET MVC project.
/*
Output:
Service1 Called
Service2 Called
Service3 Called
*/
I need some help - I am trying to use a custom validation attribute in an ASP.NET MVC web project that needs to make a database call.
I have windsor successfully working for the controllers and the IRepository interface is injected normally. The problem arrises when I need to inject the repository into the attribute class.
The attribute class has the following code:
public class ValidateUniqueUrlNodeAttribute : AbstractValidationAttribute
{
private readonly string message;
private readonly IArticleRepository articleRepository;
public ValidateUniqueUrlNodeAttribute(string message)
{
this.message = message;
}
public ValidateUniqueUrlNodeAttribute(string message, IArticleRepository articleRepository):this(message)
{
this.articleRepository = articleRepository;
}
public override IValidator Build()
{
var validator = new UniqueUrlNodeValidator(articleRepository) { ErrorMessage = message };
ConfigureValidatorMessage(validator);
return validator;
}
My problem is that I cannot seem to make Windsor intercept the contruction of the attribute to pass in the IArticleRepository
The current code in my global.asax file is as follows:
container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container));
container
.RegisterControllers(Assembly.GetExecutingAssembly())
.AddComponent<IArticleRepository, ArticleRepository>()
.AddComponent<ValidateUniqueUrlNodeAttribute>();
Any help would be greatly appreciated.
AFAIK no dependency injection container can directly manage an attribute, since it's instantiated by the runtime and there's no way to intercept that.
However, they can cheat by either:
Using a static gateway to the container (example), or
Using a "BuildUp" feature that injects whatever dependencies are found within an already-constructed object. This is called BuildUp in Unity or InjectProperties in Autofac.
Windsor doesn't support #2 (ref1, ref2), so you can either:
Try one of the hacks to make Windsor support #2 (hack1, hack2)
Use a static gateway
Implement your own IValidatorBuilder and make it use Windsor to create validators. I'm sure this is implemented somewhere but I can't find it right now...
Don't know if this helps, but I subclassed ValidationAttribute to expose a Resolve<T>() method like so:
public abstract class IocValidationAttribute : ValidationAttribute
{
protected T Resolve<T>()
{
return IocHelper.Container().Resolve<T>();
}
}
Then it can be used in any custom ValidatorAttribute that needs to hit a database:
public class UniqueEmailAttribute : IocValidationAttribute
{
public override bool IsValid(object value)
{
ICustomerRepository customerRepository = Resolve<ICustomerRepository>();
return customerRepository.FindByEmail(value.ToString()) == null;
}
}
I think it's a variation of the 'Static Gateway' approach mentioned by Mauricio Scheffer. I don't know if this is a good design or not. I'm not a huge fan of it, I'd rather the dependency was injected more 'elegantly', though I can't use constructor injection obviously, I'd like to use Property injection but can't work out a way to hook into the ASP.NET MVC framework code to do this (I've even pored though the MVC2 source code).
I was able to wire it up [using Autofac as it happens, but it's just constructor injection via the ASP.NET MVC DependencyResolver] in this answer, enabling one to write:
class MyModel
{
...
[Required, StringLength(42)]
[ValidatorService(typeof(MyDiDependentValidator), ErrorMessage = "It's simply unacceptable")]
public string MyProperty { get; set; }
....
}
public class MyDiDependentValidator : Validator<MyModel>
{
readonly IUnitOfWork _iLoveWrappingStuff;
public MyDiDependentValidator(IUnitOfWork iLoveWrappingStuff)
{
_iLoveWrappingStuff = iLoveWrappingStuff;
}
protected override bool IsValid(MyModel instance, object value)
{
var attempted = (string)value;
return _iLoveWrappingStuff.SaysCanHazCheez(instance, attempted);
}
}
With some helper classes (look over there), you wire it up e.g. in ASP.NET MVC like so in the Global.asax :-
DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(
typeof(ValidatorServiceAttribute),
(metadata, context, attribute) =>
new DataAnnotationsModelValidatorEx(metadata, context, attribute, true));
Hmm.
Can you test the effect of removing the (string message) ctor, and see if that at least forces Castle to use the ctor with the Repostiory ?
Otherwise we call AddComponent(name, type, type). Other than that it really should work...
Also does this hint at my first idea ? How do I use Windsor to inject dependencies into ActionFilterAttributes