I'm trying to use DI to bind a different implementation of my networking class. I've been able to do this successfully using a none generic version of the class. My implementation is as follows:
class MainClass
{
public static void Main(string[] args)
{
IKernel kernel;
// Hardcode here but will be managed by build system.
bool runningInProd = false;
if (runningInProd)
{
kernel = new StandardKernel(new RealNetworkModule());
}
else
{
kernel = new StandardKernel(new FakeNetworkModule());
}
Session session = kernel.Get<Session>();
session.Authenticate();
}
public class RealNetworkModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IRequestSender)).To(typeof(RealRequestSender));
}
}
public class FakeNetworkModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IRequestSender)).To(typeof(FakeRequestSender));
}
}
}
Class that uses my IRequestSender:
public class Session
{
IRequestSender requestSender;
[Inject]
public Session(IRequestSender requestSender)
{
this.requestSender = requestSender;
}
public void Authenticate()
{
Console.WriteLine(requestSender.Send("Hello There"));
}
}
The IRequestSender interface:
public interface IRequestSender
{
string Send(string request);
}
And the two different implementations:
public class RealRequestSender: IRequestSender
{
public string Send(string request)
{
return "RealRequestSender right back at you: " + request;
}
}
public class FakeRequestSender: IRequestSender
{
public string Send(string request)
{
return "FakeRequestSender right back at you: " + request;
}
}
This is very straightforward and it works; however, what I need is for my IRequestSender to use Generic types rather than string for input output:
public interface IRequestSender<RequestT, ResponseT> where RequestT: class where ResponseT: class
{
RequestT Send(RequestT request);
}
And the impl's:
public class FakeRequestSender<RequestT, ResponseT> : IRequestSender<RequestT, ResponseT> where RequestT : class where ResponseT : class
{
public RequestT Send(RequestT request)
{
throw new NotImplementedException();
}
}
public class RealRequestSender<RequestT, ResponseT> : IRequestSender<RequestT, ResponseT> where RequestT : class where ResponseT : class
{
public RequestT Send(RequestT request)
{
throw new NotImplementedException();
}
}
I've come across several examples that address this issue and I've tried to base my implementation on them but I have failed. Here are the two problems that I'm running into:
1) Binding: this is the main problem. Here is what my binding looks like based on solutions I have seen online:
public class RealNetworkModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IRequestSender<>)).To(typeof(RealRequestSender<>));
}
}
VSCode gives me the error:
Program.cs(29,29): Error CS0305: Using the generic type 'IRequestSender<RequestT, ResponseT>' requires 2 type arguments (CS0305) (DI)
Based on this error and what I have read online it is still not clear to me what I need to do here.
2) Accessing IRequestSender: the solution to this might be clear once I know how to fix binding. In the original implementation I used [Inject] to get access to the IRequestSender I need in my Sessions class. However now in the generic version I imagine I will not be able to do this. If I were to use RequestSender without DI it would look like:
RequestSender <AuthRequest, AuthResponse> requestSender = new RequestSender<AuthRequest, AuthResponse>();
or
RequestSender <UserRequest, UserResponse> requestSender = new RequestSender< UserRequest, UserResponse >();
for any number of different types.
So I'm not sure how to go about accessing the RequestSender in this scenario.
Given your current interface, you'll have to specify the generic type arguments when injecting. Assuming your request and response are both strings, your constructor would look like:
public Session(IRequestSender<string, string> requestSender)
{
this.requestSender = requestSender;
}
If you don't want to specify the arguments at creation/injection time, you'll have to change the design a bit. I can't say for certain with the sample code you provided, but it might be possible to remove the generic type args from your interface and place them on the method instead:
public interface IRequestSender
{
RequestT Send<RequestT, ResponseT>(RequestT request)
where RequestT: class
where ResponseT: class;
}
With that definition, you'd inject IRequestSender, and then specify the generic type parameters when calling. For example,
string myResponse = requestSender.Send<string, string>("my string");
Related
Think my understanding about OO is wrong.
Say I have these classes
public class BaseValidator{
public Result Validate(BaseRequest r){
xxxx
}
}
public class BaseRequest{
}
Then in my child class, I have this:
Public class ChildValidator : BaseValidator{
public Result Validate(ChildRequest r){
xxxx,
base.Validate(r);
}
}
public class ChildRequest: BaseRequest{
}
When using the classes:
BaseValidator cr = new ChildValidator();
ChildRequest r = new ChildRequest();
cr.Validate(r);
I thought this will call ChildValidator's Validate method, but turned out it calls BaseValidator's method.
What is the right way to do this? I want to pass my ChildValidator to another method, which takes BaseValidator as a parameter.
You are currently casting ChildValidator to BaseValidator, as such you are calling BaseValidator.Validate(BaseRequest) which at present has a different signature to ChildValidator.Validate(ChildRequest). You can pass an instance of ChildRequest to either method without issue because it inherits from BaseRequest.
Without this cast you would call ChildValidator.Validate() as you are expecting:
ChildValidator cr = new ChildValidator();
ChildRequest r = new ChildRequest();
cr.Validate(r); // Calls ChildValidator.Validate() method
If you want the ChildValidator.Validate() method to always be called then you would need to use a virtual / override method. You can't do that as your classes are currently written because you are accepting different parameter types (BaseRequest and ChildRequest).
Interfaces
You could utilise interfaces to help you out in this case, as shown below:
public interface IValidator {
bool Validate(IRequest r);
}
public class BaseValidator : IValidator {
public virtual bool Validate(IRequest r) {
return true;
}
}
public class ChildValidator : BaseValidator {
public override bool Validate(IRequest r) {
return base.Validate(r);
}
}
public interface IRequest { }
public class ChildRequest : BaseRequest { }
public class BaseRequest : IRequest { }
With the above classes / interfaces the original calls would work as follows:
BaseValidator cr = new ChildValidator(); // cast to BaseValidator
ChildRequest r = new ChildRequest();
cr.Validate(r); // Still calls ChildValidator.Validate() method
Generic Class
Alternatively, and as Jon Skeet pointed towards, you may want to look at implementing a generic Validator class. That could perhaps look something like the below:
public class Validator<T> where T : BaseRequest {
public bool Validate(T r) {
return true;
}
}
public class BaseRequest { }
public class ChildRequest : BaseRequest { }
You can use that as below:
var validator = new Validator<ChildRequest>();
ChildRequest request = new ChildRequest();
validator.Validate(r);
The best method for you will depend on the rest of your implementation and what the methods are doing.
This is probably a classic covariance/contravariance question, it looks like it should work but I'm probably missing a trick.
I'm attempting to return a less derived type from a factory method, but I find that I cannot cast the more specialized concrete instance to a less derived base type.
public class AnimalSettings { ... }
public class CatSettings : AnimalSettings { ... }
public interface IAnimalService<TSettings> { ... }
public abstract AnimalService<TSettings> : IAnimalService<TSettings> where TSettings : AnimalSettings { ... }
public class CatService : AnimalService<CatSettings> { ... }
Then, in a factory method I have:
public static IAnimalService<AnimalSettings> GetAnimalService(AnimalType selector)
{
switch (selector)
{
case AnimalType.Cat:
return (IAnimalService<AnimalSettings>) new CatService();
break;
}
}
and the intention is to be able to do the following:
var service = MyServiceFactory.GetAnimalService(AnimalType.Cat);
service.DoAnimalBehavior();
This compiles fine, but at runtime my code is failing in the attempted cast return (IAnimalService<AnimalSettings>) new CatService();, with an InvalidCastException.
How should I be casting my more derived type to a less derived type so that callers can use that interfaced base type to invoke functionality?
Changing the cast to (IAnimalservice<CatSettings>) new CatService() does work, but it's intended that the caller receives a IAnimalservice<AnimalSettings> so that it can handle any sort of animal (In other words, the caller should not be using any of the more specialized types). Should I be specifying an in or out as part of the generic definition somewhere?
By giving a complete example it would be much easier to help. ;-)
So here is the working code. And as Sweeper already mentioned, you need to add the out parameter at the interface to make it work.
using System;
public class Program
{
public static void Main()
{
var catService = new CatService(new CatSettings());
var genericService = (IAnimalService<AnimalSettings>)catService;
genericService.DoAnimalBehavior();
}
}
public abstract class AnimalSettings
{
public abstract void DoAnimalBehavior();
}
public class CatSettings : AnimalSettings
{
public override void DoAnimalBehavior()
{
Console.WriteLine("Meeoh");
}
}
public interface IAnimalService<out TSettings>
{
void DoAnimalBehavior();
}
public abstract class AnimalService<TSettings> : IAnimalService<TSettings> where TSettings : AnimalSettings
{
private readonly TSettings _settings;
public AnimalService(TSettings settings)
{
_settings = settings;
}
public void DoAnimalBehavior()
{
_settings.DoAnimalBehavior();
}
}
public class CatService : AnimalService<CatSettings>
{
private readonly CatSettings _catSettings;
public CatService(CatSettings catSettings)
: base(catSettings)
{
_catSettings = catSettings;
}
}
This is my interface:
public interface ISocialService<T> where T : ISocialModel
{
public Task<List<T>> GetPosts();
}
I have 2 implementations of this interface.
This is how I try to register them
services.AddScoped<ISocialService<RedditPost>, RedditService>();
services.AddScoped<ISocialService<HackerNewsModel>, HackerNewsService>();
And finally this is how I try to resolve them.
public ScrapeJob(IEnumerable<ISocialService<ISocialModel>> socialServices)
{
_socialServices = socialServices;
}
However socialServices is empty.
I think the problem lies in ISocialModel.
Anyone got suggestions how can I register or resolve them properly?
The reason why I want to use a generic interface is I want to inject specific service into a controller like this:
public HackerNewsController(ISocialService<HackerNewsModel> socialService)
{
_socialService = socialService;
}
The problem is you have injected generic interface IEnumerable<ISocialService<ISocialModel>> but you don't have any classes that implement ISocialService<ISocialModel> instead you have ISocialService<T> implementation in classes.
so we need to update the code following way for example
public interface ISocialModel
{
}
public class RedditModel : ISocialModel
{
}
public interface ISocialService
{
Task<List<ISocialModel>> GetPosts();
}
public interface ISocialService<T>: ISocialService where T : ISocialModel
{
Task<List<T>> GetPosts();
}
public abstract class SocialServiceBase<T> : ISocialService<T> where T : ISocialModel
{
async Task<List<ISocialModel>> ISocialService.GetPosts()
{
var posts = await GetPosts();
return posts.Cast<ISocialModel>().ToList();
}
public abstract Task<List<T>> GetPosts();
}
public class RedditSocialService : SocialServiceBase<RedditModel>
{
public override Task<List<RedditModel>> GetPosts()
{
//TODO: past your implementation here
}
}
so in registration now you can write following code
services.AddScoped<ISocialService, RedditService>();
services.AddScoped<ISocialService, HackerNewsService>();
and later in class you can use like that
class ScrapeJob
{
private IEnumerable<ISocialService> _socialServices;
public ScrapeJob(IEnumerable<ISocialService> socialServices)
{
_socialServices = socialServices;
}
public async Task DoScrapeJob()
{
foreach( var service in _socialServices)
{
var posts = await service.GetPosts();
}
}
}
Have a look at this link:
https://www.stevejgordon.co.uk/asp-net-core-dependency-injection-registering-multiple-implementations-interface
You may need to register ISocialModel for both in order for it to be recognized as a collection of IEnumerable:
e.g.
services.AddScoped<ISocialModel, RedditService>();
services.AddScoped<ISocialModel, HackerNewsService>();
I'm using Unity in with C#. I have an interface I call IConnectionStringLoader, which have two derived interfaces.
public interface IConnectionStringLoader
{
string Get();
void Write();
}
public interface IDbConnectionStringLoader : IConnectionStringLoader
{
}
public interface IMetaDataConnectionStringLoader : IConnectionStringLoader
{
}
It has only one implementation:
public class ConnectionStringLoader : IDbConnectionStringLoader, IMetaDataConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
My registration looks like this:
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("DbConnection"));
The point of the interfaces is that I can inject the different interfaces in my classes and get the correct connectionstring for each implementation. But the problem is that whatever registration is done last will overwrite the previous one.
var foo = _container.Resolve<IDbConnectionStringLoader>();
var bar = _container.Resolve<IMetaDataConnectionStringLoader>();
foo.Write();
bar.Write();
Output is:
DbConnection
DbConnection
If I invert the order of the registration the output will be MetaConnection twice. So my conclusion so far is that the last registration overwrites the previous one. However, if I change the implementation to a derived class it works:
public class SomeOtherConnectionStringLoader : ConnectionStringLoader
{
public ConnectionStringLoaderImpl(string connectionStringName) : base(connectionStringName)
{
}
}
And change the registrations:
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, SomeOtherConnectionStringLoader >(new InjectionConstructor("DbConnection"));
Now everything works, but I don't understand why. I've tried different lifetimemanagers, but with the same result. I thought Unity would try to create an instance of ConnectionStringLoader with the "correct" injectionparameter based on the interface, but there's seems to be some other logic at play here.
Any suggestions why the registrations overwrite each other?
Honestly speaking, the way you are using the interfaces looks strange to me because there are two interfaces implemented only by the same class. I would find more natural to follow the next approach using registration names:
// If it is a loader the Write method makes no sense (IConnectionStringRepository?)
public interface IConnectionStringLoader
{
string Get();
void Write();
}
public class ConnectionStringLoader : IConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
Registrations:
container.RegisterType<IConnectionStringLoader, ConnectionStringLoader>("Database", new InjectionConstructor("MetaConnection"));
container.RegisterType<IConnectionStringLoader, ConnectionStringLoader>("Metadata", new InjectionConstructor("DbConnection"));
Resolutions:
var foo = _container.Resolve<IConnectionStringLoader>("Database");
var bar = _container.Resolve<IConnectionStringLoader>("Metadata");
foo.Write();
bar.Write();
I'm not familiar with Unity. But it seems they are mapping to same instance. So you should change lifetime of ConnectionStringLoader (Per dependency).
If you will not share instance, why do you put all things in one class ? ConnectionStringLoader Methods = IDbConnectionStringLoader methods + IMetaDataConnectionStringLoader methods.
When you resolve IDbConnectionStringLoader it will not use IMetaDataConnectionStringLoader methods which is already in instance (vice versa it's true).
Crating two different derived class is better at this point:
Abstract class:
public abstract class ConnectionStringLoader : IConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
Derived Classes:
public sealed class DbConnectionStringLoader : ConnectionStringLoader, IDbConnectionStringLoader
{
public DbConnectionStringLoader(string connectionStringName):base(connectionStringName)
{
}
//Implement methods here just belongs to IDbConnectionStringLoader
}
public sealed class MetaDataConnectionStringLoader : ConnectionStringLoader, IMetaDataConnectionStringLoader
{
public MetaDataConnectionStringLoader(string connectionStringName):base(connectionStringName)
{
}
//Implement methods here just belongs to IMetaDataConnectionStringLoader
}
Surprisingly it does call ConnectionStringLoader ctor twice, but with same injection member. If you look at container.Registrations, there are indeed two registrations so it is not override one with other. I did look at implementation of RegisterType, but didn't get my head around it.
One alternative is to name your registrations, not sure if it fits into your overall unity bootstrap strategy.
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>("bar", new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, ConnectionStringLoader>("foo", new InjectionConstructor("DbConnection"));
var foo = container.Resolve<IDbConnectionStringLoader>("foo");
var bar = container.Resolve<IMetaDataConnectionStringLoader>("bar");
This will be generics 101 for many but below is sample code so I can understand better.
public interface IRecordedItemsProcessor<T>
{
ObservableCollection<RecordedItem> Load(string name);
void Save();
RecordedItem Parse(T itemToParse);
}
public class FileLoadingProcessor : IRecordedItemsProcessor<string>
{
public ObservableCollection<RecordedItem> Load(string name)
{
}
public void Save()
{
}
public RecordedItem Parse(string itemToParse)
{
}
}
public class MyClass
{
public MyClass(IRecordedItemsProcessor<T> processor)
{
}
}
The issue is that MyClass needs a dependency on IRecordedItemsProcessor<T> but will not compile as it does not know what T is. How can this be resolved? Making MyClass implement a seems odd as all it needs to do is call Load/Save
Thanks
First solution is the most simple one: lift generic declaration to class level, like
public class MyClass<T>
{
public MyClass(IRecordedItemsProcessor<T> processor)
{
}
}
Then you could instantiate MyClass as following:
var myClass = new MyClass<string>(new FileLoadingProcessor());
Console.WriteLine (myClass);
Second solution is a removing generic input from constructor and inferring types. Then you don't need to specify generic exactly from call. Class declaration will look like:
public class MyClass
{
public void Process<T>(IRecordedItemsProcessor<T> processor)
{
}
}
And then you can call simply
var my = new MyClass();
my.Process(new FileLoadingProcessor());
The Idea is that you always need to specify class-level generics explicitly, but method level generics can be inferred by the compiler.
Third solutions is to encapsulate creation mechanisms inside MyClassFactory. This is quite flexible, but it might seem a little bit complicated, because descendants of IRecordedItemsProcessor<T> don't define generic at class level, so we should go to implemented interfaces and grab there generic types. And only then we can construct Generic MyClass. Listing is given below:
public class MyClassFactory
{
public MyClass<T> MakeMyClassFor<T>(IRecordedItemsProcessor<T> processor)
{
var processorGenericType = processor.GetType()
.GetInterfaces()
.Single(intr=>intr.Name == "IRecordedItemsProcessor`1")
.GetGenericArguments()[0];
var myClassType = typeof(MyClass<>).MakeGenericType(processorGenericType);
return Activator.CreateInstance(myClassType, processor) as MyClass<T>;
}
}
Now you can create MyClass very simply
var myClassFactory = new MyClassFactory();
var res = myClassFactory.MakeMyClassFor(new FileLoadingProcessor());
Console.WriteLine (res);
All of these three approaches have their pros and cons. Consider taking into account the context, in which you are going to use them.
You could do the following:
Create a new interface IRecordedItemsProcessor (non-generic)
Move Load and Save to this IRecordedItemsProcessor
Make IRecordedItemsProcessor<T> inherit from this IRecordedItemsProcessor
Make MyClass expect IRecordedItemsProcessor in its constructor
This makes it clear that MyClass doesn't care what type the processor might be able to parse, or even that it can parse things at all - it only knows that it can save and load.
You could inherit from a non-generic marker interface, this removes the need to know about T in your class:
public interface IRecordedItemsProcessor
{
}
public interface IRecordedItemsProcessor<T> : IRecordedItemsProcessor
{
ObservableCollection<RecordedItem> Load(string name);
void Save();
RecordedItem Parse(T itemToParse);
}
And then you can use any IRecordedItemsProcessor like:
public class MyClass
{
public MyClass(IRecordedItemsProcessor processor)
{
}
}
The generic type, as written, is being declared on the MyClass constructor which means the generic type must be defined at the MyClass level:
public class MyClass<T>
{
public MyClass(IRecordedItemsProcessor<T> processor)
{
}
}
However, if the generic type was declared at a method level, it would only have to be defined at the method level:
public class MyClass
{
public void MyMethod<T>( IRecordedItemsProcessor<T> processor )
{
}
}
EDIT
Based on your comment:
I want a class that can call the Load/Save methods but not be worried
that T is.
Then you'll need 2 interfaces: 1 for the load/save and then one with the parsing. In this case, you could use inheritance:
public interface IRecordedItems
{
ObservableCollection<RecordedItem> Load( string name );
void Save();
}
public interface IRecordedItemsProcessor<T> : IRecordedItems
{
RecordedItem Parse( T itemToParse );
}
public class MyClass : IRecordedItems
{
#region Implementation of IRecordedItems
public ObservableCollection<RecordedItem> Load( string name )
{
throw new NotImplementedException();
}
public void Save()
{
throw new NotImplementedException();
}
#endregion
}
EDIT 2
Based on your gist example, the type dependency could be moved off of the interface and directly into the interface method:
public class RecordedItem {}
public interface IRecordedItemsProcessor
{
ObservableCollection<RecordedItem> Load( string name );
void Save();
RecordedItem Parse<T>( T itemToParse );
}
public class MyClass
{
private readonly IRecordedItemsProcessor _processor;
public MyClass( IRecordedItemsProcessor processor )
{
_processor = processor;
processor.Parse<string>( "foo" );
processor.Parse<int>( 10 );
processor.Parse<RecordedItem>( new RecordedItem() );
}
}