I have the following interface hierarchy:
public interface IActor { ... }
public interface IHealthUser : IActor { ... }
and a third interface:
public interface IAction { void Perform(IActor caster) }
Why is the following not legal and can I get around it somehow?
public class HealthPotion : IAction
{
public void Perform(IHealthUser caster) { ... }
}
The contract defined by IAction states that you can Perform the action on any IActor. Any IActor. Not only IHealthUser. What your HealthPotion tries to do is only implement a subset of IAction, meaning to perform its task only on a subset of IActors. That's not what the IAction interface states.
If you want a specific IAction to be able to restrict the type of IActor it applies to, you can do it using generic constraints:
public interface IAction<TAppliesTo> where TAppliesTo : IActor
{
void Perform(TAppliesTo appliesTo);
}
public class UniversalAction : IAction<IActor>
{
public void Perform (IActor anyone) {}
}
public class HealthPotion : IAction<IHealthUser>
{
public void Perform (IHealthUser healthUserOnly){}
}
You need to implement the same signature as your interface defines. You are using IActor in the interface but then you are using IHealthUser in the implementation of IAction interface. You should implement the Perform with the IActor parameter. It can be called however with class that implements IHealthUser.
Related
Note: This is similar to this Question
My Question is if I have interfaces defined like below:
(NOTE: My code has more than one derived level; example for simplicity)
public interface IHandler
{
void Handle(IBaseCommand command);
}
public interface IHandler<out T> : IHandler where T : IBaseCommand { }
public interface IBaseCommand { }
public interface IDerivedCommand : IBaseCommand { }
public class BaseCommand : IBaseCommand { }
public class DerivedCommand : IDerivedCommand { }
public class BaseCommandHandler : IHandler<IBaseCommand>
{
public void Handle(IBaseCommand command) { }
}
public class DerivedCommandHandler : IHandler<IDerivedCommand>
{
public void Handle(IBaseCommand command) { }
public void Handle(IDerivedCommand command) { }
}
My snippet of registrations for this example looks like:
builder.RegisterType<DerivedCommand>().AsImplementedInterfaces();
builder.RegisterType<BaseCommand>().AsImplementedInterfaces();
builder.RegisterType<DerivedCommandHandler>().AsImplementedInterfaces();
builder.RegisterType<BaseCommandHandler>().AsImplementedInterfaces();
This container.Resolve<IEnumerable<IHandler<IBaseCommand>>>(); only returns BaseCommandHandler.
I need to get BaseCommandHandler and all derived types, which in this instance would include DerivedCommandHandler too.
I realize this registration container.Resolve<IEnumerable<IHandler>>(); will resolve ALL handlers but I need to be able to resolve any where in the derived chain.
QUESTION: How do I resolve all handlers starting from a specific derived service?
You chould change this:
IHandler<out T>
to:
IHandler<in T>
Let's say I have a class called UIViewController.
public class UIViewController
{
// ... methods
}
And I have an interface IDoFancyFlips
public interface IDoFancyFlips
{
// ... methods
}
I have a classes that extend UIViewController and implement the interface as follows.
public class FancyViewController : UIViewController, IDoFancyFlips
{
// ... methods
}
Now I want to write a method that takes a UIViewController as a parameter, but only ones that implement IDoFancyFlips.
public void FlipAndShow(??? controller) {
// implementation
}
My question is what do I put in the ???. I couldn't seem to find any way to do this.
I can do this in Objective C as follows:
- (void) flipAndShow:(UIViewController<IDoFancyFlips>*) controller {
// implementation
}
But I can't find the equivalent declaration in C#.
You can use generics to accomplish this. Try the following:
public void FlipAndShow<TFancyFlippingController>
(TFancyFlippingController fancyFlippingController)
where TFancyFlippingController : UIViewController, IDoFancyFlips
{
// implementation
}
The where TFancyFlippingController : UIViewController, IDoFancyFlips constraint ensures that the argument specified for TFancyFlippingController must both inherit from UIViewController and implement the IDoFancyFlips interface.
Considering that all your specific view controller inherits from base UIViewController class
public class FancyViewController : UIViewController, DoFancyFlips
{
// ... methods
}
public class NormalViewController : UIViewController
{
// ... methods
}
you can check at runtime whether the passed instance is of type DoFancyFlips and then do the processing further; like
public static void FlipAndShow(UIViewController controller)
{
if (!(controller is DoFancyFlips))
return;
// implementation
}
I don't know whether I'm approaching this from the right angle or not, but either way I can't find syntax that works.
I want to pass 3 generic types to a method - from there I'll use reflection to create objects when I need them. However the object I'm passing is itself generic.
It sort of sounds like nested generics.
Let's say I create an interface:
public interface IAgent<TRequest, TClient, TResponse>
{
}
I have a class like this that implements IAgent:
public class MyClass : IAgent<?>
Then I want to call a method something like this:
public method MyMethod<T>(T obj) where T : IAgent<?>
{
// do somethings here
}
UPDATE
Here's what I currently do at class level.
public sealed class T3Agent
: AppAgent<T3RequestAdapter, T3WebClient, T3ResponseAdapter>
{
}
public abstract class AppAgent<TRequest, TClient, TResponse>
where TRequest : IAgentRequestAdapter
where TClient : CustomWebClient
where TResponse : IAgentResponseAdapter
{
public AppResponse Submit(IAppForm appForm, ServiceLog log)
{
}
}
public sealed class AppManager
{
public AppResponse Submit()
{
var t3 = new T3Agent();
var t3Result = t3.Submit(Form, Log);
return t3Result;
}
}
In the final method, I instantiate a new class (T3Agent), but this is tightly coupled to T3. I want to be able to instantiate AppAgent once and pass the required generic types through the method rather than the class, so that I can reuse the class.
I think you have 2 options:
if you have to work with generic class T from Agent<T> you have to know the type anyway so you have to put it in your generic declaration (see TypeNeeded() method below)
If it is not necessary, then split up the interface in a not generic and in a generic interface and then let IAgent<T> extend IAgent (IAgent<T>: IAgent). Now you can create a method without to know the type for IAgent<T> (see method DoSomething())
public interface IAgent
{
void Action( );
int Calculate( );
}
public interface IAgent< T > : IAgent
{
void Set( T value );
}
public class MyClass
{
public void DoSomething< T >( T agent ) where T : IAgent
{
//...
}
public void TypeNeeded< T, V >( T agent ) where T : IAgent<V>
{
}
}
If you don't know the types for your generic interface yet, your class or method needs to be generic, too:
public class MyClass<TRequest, TClient, TResponse> : IAgent<TRequest, TClient, TResponse>
{
}
Or for the method:
public void MyMethod<T, TRequest, TClient, TResponse>(T obj) where T : IAgent<TRequest, TClient, TResponse>
{
// do somethings here
}
I have the following classes:
// -- model hierarchy
public interface IJob {
}
public abstract class AbstractJob : IJob {
}
public class FullTimeJob : AbstractJob {
}
// -- dao hierarchy
public interface IJobDao<T> where T : IJob {
T findById(long jobId);
long insert(T job);
}
public interface IFullTimeJobDao : IJobDao<FullTimeJob> {
}
public abstract class AbstractDao {
}
public abstract class AbstractJobDaoImpl<T> : AbstractDao, IJobDao<T> where T : IJob {
public T findById(long jobId) {
// omitted for brevity
}
public long insert(T job) {
// omitted for brevity
}
}
public class FullTimeJobDaoImpl : AbstractJobDaoImpl<FullTimeJob>, IFullTimeJobDao {
}
I'm calling the following code from a factory method, which does not seem to work:
public IJobDao<IJob> createJobDao(long jobDaoTypeId)
{
object jobDao = Activator.CreateInstance(typeof(FullTimeJobDaoImpl));
return jobDao as IJobDao<IJob>; // <-- this returns null
return (IJobDao<IJob>) jobDao; // <-- this cast fails
}
How is this "up cast" properly achieved?
Make IJobDao interface covariant:
public interface IJobDao<out T> where T : IJob
{
T findById(long jobId);
}
Update:
You cannot have interface methods both returning and accepting generic values and make it covariant at the same time.
Possible solutions:
create a non-generic version of IJobDao<T> - IJobDao (of course, you'll have to implement both interfaces in classes, implementing IJobDao<T>)
split IJobDao<T> into 2 interfaces (one covariant and one contravariant)
consider a solution with only non-generic interface IJobDao (you are not getting any type-safety here anyway, which is the main purpose of generics)
Some ideas on implementing first scenario:
public interface IJobDao
{
IJob findById(long jobId);
long insert(IJob job);
}
public interface IJobDao<T> : IJobDao
where T : IJob
{
new T findById(long jobId);
new long insert(T job);
}
public abstract class JobDaoBase<T> : IJobDao<T>, IJobDao
where T : IJob
{
public abstract T findById(long jobId);
public abstract long insert(T job);
IJob IJobDao.findById(long jobId)
{
return findById(jobId);
}
long IJobDao.insert(IJob job)
{
return insert((T)job);
}
}
public class FullTimeJobDaoImpl : JobDaoBase<FullTimeJob>
{
public override FullTimeJob findById(long jobId)
{
// implementation
}
public override long insert(FullTimeJob job)
{
// implementation
}
}
// we are still unable to return generic interface, but we don't need to.
public static IJobDao createJobDao(/* my params */)
{
object jobDao = Activator.CreateInstance(typeof(FullTimeJobDaoImpl));
return jobDao as IJobDao;
}
For this cast to be possible you'll need to mark the interface type parameter as out:
public interface IJobDao<out T> where T : IJob {...}
Then
object jobDao = Activator.CreateInstance(typeof(FullTimeJobDaoImpl));
var r = jobDao as IJobDao<IJob>; //not null
But this brings some restrictions on the interface. Read out (Generic Modifier) (C# Reference) for more info.
In a generic interface, a type parameter can be declared covariant if
it satisfies the following conditions:
The type parameter is used only as a return type of interface methods and not used as a type of method arguments.
The type parameter is not used as a generic constraint for the interface methods.
Consider using Inversion of Control approach with a container. The various implementations register themselves in the container. The resolver enquires please an instance of (x).
See Unity as 1 of many IOC Container tools.
I have the following and at some point I need to create Failures for Validations. We suppose each type deriving from Validation has one and only one type deriving from Failure<T> where T is the aforementioned implementation of Validation.
As I have a growing number of implementations of Validation, I need to be able to instantiate the right type deriving from Failure<T>, and call the link method on it within a method that looks like
void recordFailureForValidation(Validation v) {
Type failureType = dict[v.GetType()];
Object failure = Activator.CreateInstance(failureType);
// how do I call failure.link(v) ?
}
At Runtime, a dictionary gives me the type deriving from Failure<T> given T.
I am able to instantiate Failure<T> (Failure1, Failure2, etc...), but I can't find how to call link on the public field reference of my newly created Failure instance (by making all uses that made sense to me of GetMethod, MakeGenericMethod, Invoke, etc...)
public class MyReferenceClass<T>
where T : Object, new() {
public void link(T arg) { ... }
}
public abstract class Failure<T>
where T : ValidationRule, new() {
...
public MyReferenceClass<T> reference;
...
}
public class Failure1 : Failure<Validation1> {
}
public class Failure2 : Failure<Validation2> {
}
public abstract class ValidationRule {
...
}
public class ValidationRule1 : ValidationRule {
...
}
public class ValidationRule2 : ValidationRule {
...
}
link is private since you do not specify a different accessibility. Make it public or internal:
public class MyReferenceClass<T>
where T : Object, new() {
public void link(T arg) { ... }
}
then you can call it from Failure<T> through the reference property:
public abstract class Failure<T>
where T : ValidationRule, new()
{
protected T Validation {get; set;};
public MyReferenceClass<T> reference;
}
public class Failure1 : Failure<Validation1>
{
public void Test()
{
this.reference.link(Validation);
}
}
Let Failures implement a non generic IFailure interface as well as a generic one in the same manner as IEnumerable and IEnumerable<T>
Create an abstract factory method within ValidationRule that has to be implemented by each concrete Validation
public ValidationRule1 : ValidationRule
{
public override IFailure ToFailure()
{
return new Failure1(this);
}
...
}