Narrowing a generic interface - c#

I am attempting to write a "Task" system for a game that can take in generic "GameTasks" with Payloads, however I think I am having a problem with covariance.
This is the function that adds the task to the repository
internal void AddTask(IGameTask<IPayload> task)
{
Tasks.Add(task);
Broker.Instance.Publish(new TaskAdded(task));
}
The repository is currently just a list
public List<IGameTask<IPayload>> Tasks { get; } = new();
This is the task and payload I am attempting to add
public interface IBuildTaskPayload : IPayload
{
public float ContributeAmount { get; }
}
/// <summary>
/// Created when a building is placed
/// </summary>
public class BuildTask : IGameTask<IBuildTaskPayload>
{
...
/// <inheritdoc />
public TaskStatus UpdateTask(IBuildTaskPayload updatePayload)
{
Progress += updatePayload.ContributeAmount;
return Progress >= 100 ? TaskStatus.Finished : TaskStatus.Executing;
}
}
And attempting to add it to the repository
TaskRepository.Instance.AddTask(new BuildTask(construction));
This last part fails, as BuildTask cannot be cast to IGameTask. Why is this? And how would I go about achieving this correctly?

You make have to remove the generics from IGameTask<IPayLoad>
You don't show the definition, but to remove the generic parameter you do something like this
public interface IGameTask
{
IPayLoad PayLoad { get; }
}
This solves the problem that you have which stems from the fact that each implementation of IGameTask<> is a different type.
For example
public interface IPayLoad { }
public interface IGameTask
{
IPayLoad PayLoad { get; }
}
public class BuildingAssets : IPayLoad
{
}
public class BuildTask : IGameTask
{
public BuildingAssets PayLoad { get; }
IPayLoad IGameTask.PayLoad { get => PayLoad; }
}
to be used as
List<IGameTask> tasks = new List<IGameTask>();
// fill list
foreach (var task in tasks)
{
if (task is BuildTask build)
{
BuildingAssets assets = build.PayLoad;
}
}

Related

How to enforce method execution order in c#

Long story short, i have following class:
public class FlowBasePipeline<T>
{
private List<StepBaseBusiness<T>> stepList = new List<StepBaseBusiness<T>>();
public void Push(StepBaseBusiness<T> step)
{
stepList.Add(step);
}
public void Trigger(T result)
{
foreach (var step in stepList )
{
result = step.Execute(result);
if (!result.IsSuccess)
{
break;
}
}
}
}
What I'm looking for is forcing programmer to call Push method in the first place and then give them access to Trigger method, in this case following scenario is not allowed
var pipeline=new FlowBasePipeline<MyStepResult>();
pipeline.Trigger()// Trigger method is not recognized
we should first call Push method
var pipeline=new FlowBasePipeline<MyStepResult>();
pipeline.Push(new MyStep()).Trigger()//Now Trigger is recognized
What I've done:
I applied explicit interface method implementation as follows to get it to work:
public interface IBasePipeline<T> where T:BaseResult,new()
{
void Trigger();
IBasePipeline<T> Push(StepBaseBusiness<T> step);
}
public class FlowBasePipeline<T>:IBasePipeline<T> where T:BaseResult,new()
{
private List<StepBaseBusiness<T>> stepList = new List<StepBaseBusiness<T>>();
public IBasePipeline<T> Push(StepBaseBusiness<T> step)
{
stepList.Add(step);
return this;
}
void IBasePipeline<T>.Trigger(T result)
{
foreach (var step in stepList )
{
result = step.Execute(result);
if (!result.IsSuccess)
{
break;
}
}
}
}
Now it works well and we don't have access to Trigger method before Push method, but from my prospective it's not a good way as we might need more level of orders and i don't know how it could be done in this way.
As i know, method chaining is one of the key rules of functional programming.
Is there any pattern or strategy to implement this kind of chaining?
Update:
we need to call push method multiple times
var pipeline=new FlowBasePipeline<MyStepResult>();
pipeline.Push(new MyStep1()).Push(new MyStep2()).Trigger();
After first push, push and trigger would be available.
One way to do this is to use interfaces to restrict access to specific methods by specifying an interface as the result.
public interface IStartCar
{
IDriveCar Start(string key);
}
public interface IDriveCar
{
IParkCar Drive(string address);
}
public interface IParkCar
{
IStopCar Park();
}
public interface IStopCar
{
IParkCar Drive(string address);
void Stop();
}
public class Car : IStartCar, IDriveCar, IParkCar, IStopCar
{
public IDriveCar Start(string key);
public IParkCar Drive(string address);
public IStopCar Park();
public IStopCar Park();
private Car() { }
public static IStartCar Get()
{
var result = new Car();
return result;
}
}
Now to get a Car you use the CarFactory method Get(), it returns a car, but you really only have access to the interface result. This pattern only allows developers to string specific methods together:
var car = Car.Get();
car.Start("key").Drive("address1").Park().Drive("address2").Park().Stop();
Example of approach I use for api's that inherently 'guide' the callers with a fluent syntax:
public class Pipeline
{
readonly List<Action> _steps = new List<Action>();
// only Push is available when Pipeline is initialized
public PipelineWithSteps Push(Action step)
{
_steps.Add(step);
// or cache this if you want 'Push' repeatable
return new PipelineWithSteps(this);
}
public class PipelineWithSteps
{
// not required but often the chained context wants/needs access to the first context
readonly Pipeline _context;
// api is public but ctor cannot be invoked by external caller
internal PipelineWithSteps(Pipeline context) => _context = context;
// now Trigger is available only after something was pushed
public PipelineWithSteps Trigger()
{
foreach(var step in _context._steps)
step();
Console.WriteLine();
return this;
}
// usually I don't repeat an initialization method;
// this could be done using the 'context'
// but would have to be refactored to return the existing 'PipelineWithSteps'
public PipelineWithSteps Push(Action step)
{
_context._steps.Add(step);
return this;
}
}
}
Usage:
var pipeline = new Pipeline();
pipeline.Push(() => Console.WriteLine("A"))
.Push(() => Console.WriteLine("B"))
.Trigger()
.Push(() => Console.WriteLine("C"))
.Trigger();
Output:
A
B
A
B
C
After hours ,i came up with this design:
public interface IBasePipelineRegister<T> where T:BaseResult
{
IStagePipeline<T> Push(StepBaseBusiness<T> step);
List<StepBaseBusiness<T>> Steps { get; set; }
}
public interface IBasePipelineTrigger<T> where T:BaseResult
{
void Trigger(T result);
}
public interface IStagePipeline<T>: IBasePipelineTrigger<T>,IBasePipelineRegister<T> where T:BaseResult
{
}
public class FlowBasePipeline<TResult> : IBasePipelineRegister<TResult> where TResult : BaseResult,new()
{
public List<StepBaseBusiness<TResult>> Steps { get ; set ; }
private IStagePipeline<TResult> _stagePipeline;
public BasePipeline()
{
this.Steps = new List<StepBaseBusiness<TResult>>();
this._stagePipeline = new StagePipeline<TResult>(this);
}
public IStagePipeline<TResult> Push(StepBaseBusiness<TResult> step)
{
Steps.Add(step);
return _stagePipeline;
}
}
As you see, BasePipeline just implements IBasePipelineRegister and Register method presents new StagePipeline class that is consist of current class plus trigger implementation.
public class StagePipeline<T>: IStagePipeline<T> where T:BaseResult
{
private readonly IBasePipelineRegister<T> pipelineRegister;
public List<StepBaseBusiness<T>> Steps { get; set; }
public StagePipeline(IBasePipelineRegister<T> pipelineRegister)
{
this.pipelineRegister = pipelineRegister;
Steps = pipelineRegister.Steps;
}
public IStagePipeline<T> Push(StepBaseBusiness<T> step)
{
return pipelineRegister.Push(step);
}
public void Trigger(T result)
{
foreach (var step in Steps)
{
result = step.Execute(result);
if (!result.IsSuccess)
{
break;
}
}
}
}
Now each method adds a new feature not replacing new one.
var pipeline=new FlowBasePipeline<MyStepResult>();
pipeline.Push(new MyStep1()).Push(new MyStep2()).Trigger();

Generic system for inferring the type of class required from given parameter type

I have a basic architecture for 'orders' in my game - each order has a basic data type and an 'order processor' which performs some action based on the given data. For example 'move to this point.'
I'd like to have a tidy system where I can simply pass in order data and the correct order processor will kick in, in such a way that I can easily add new OrderData/OrderProcessor classes without modifying other classes or messing around with enums or casting, so it seems like generics are the way to go.
This is the current code I have. I'm drawing a blank for how to draw a connection in the 'OrderService' class between the correct 'OrderProcessor' and 'IOrderData' pairs. See inside the OrderService<T> class for more information:
public interface IOrderData
{
}
// an order processor reads data from an IOrderData object until the data object says stop
public abstract class OrderProcessor<T> where T : IOrderData
{
protected T m_currentData;
public virtual void Start(T data)
{
m_currentData = data;
}
}
////////////////////////
public class MoveOrderData : IOrderData
{
public Vector3 Destination { get; private set; }
}
public class MoveOrderProcessor : OrderProcessor<MoveOrderData>
{
public override void Start(MoveOrderData data)
{
base.Start(data);
}
}
////////////////////////
public class OrderService<T> where T : IOrderData
{
private Dictionary<System.Type, OrderProcessor<T>> m_processors = new Dictionary<System.Type, OrderProcessor<T>>();
private OrderProcessor<T> m_currentProcessor;
public void GiveOrder(IOrderData data)
{
// this is the main problem: I'm not sure how to say "the given data is type 'MoveOrderData' so find out which
// OrderProcessor class handles those and pass it in". A simple switch statement and cast would suffice here
// but I'd like to automate the process
}
}
A possible solution here can be a making an OrderService class non-generic, because it can handle a different types of orders/order processors (according to comments). Then maintain a Dictionary<Type, Action<object>>, which wraps Action<object> to call Start method from OrderProcessor<T>.
I've extended the original code a little bit to show how it can work
public interface IOrderData
{
}
public class MoveOrderData : IOrderData
{
public Vector3 Destination { get; private set; }
}
public class AttackOrderData : IOrderData
{
}
public abstract class OrderProcessor<T> where T : IOrderData
{
protected T CurrentData { get; set; }
public virtual void Start(T data)
{
CurrentData = data;
}
}
public class MoveOrderProcessor : OrderProcessor<MoveOrderData>
{
}
public class AttackOrderProcessor : OrderProcessor<AttackOrderData>
{
}
public class OrderService
{
private readonly Dictionary<Type, Action<object>> m_processors = new Dictionary<Type, Action<object>>();
public OrderService()
{
AddProcessor(new MoveOrderProcessor());
AddProcessor(new AttackOrderProcessor());
}
private void AddProcessor<T>(OrderProcessor<T> processor) where T : IOrderData
{
var action = (Action<T>)processor.Start;
m_processors.Add(typeof(T), obj => action((T)obj));
}
public void GiveOrder(IOrderData data)
{
var action = m_processors[data.GetType()];
action?.Invoke(data);
}
}
It causes a downcasting obj => action((T)obj), but it shouldn't be a problem, since your data is constrained to IOrderData interface. Example of the usage
var service = new OrderService();
service.GiveOrder(new MoveOrderData());
service.GiveOrder(new AttackOrderData());

How to instantiate a class as the interface that it derives from with constrained generic type parameter

There's the following interface which defines a packet.
public interface IPacket
{
int Size { get; }
}
There are two implementations, each with its own additional property.
public class FooPacket : IPacket
{
public int Size => 10;
public string FooProperty { get; set; }
}
public class BarPacket : IPacket
{
public int Size => 20;
public string BarProperty { get; set; }
}
The above is library code I have no control over. I want to create a handler for packets
public interface IPacketHandler<T> where T : IPacket
{
void HandlePacket(T packet) ;
}
and create two implementations for the concrete packets.
public class FooPacketHandler : IPacketHandler<FooPacket>
{
public void HandlePacket(FooPacket packet) { /* some logic that accesses FooProperty */ }
}
public class BarPacketHandler : IPacketHandler<BarPacket>
{
public void HandlePacket(BarPacket packet) { /* some logic that accesses BarProperty */ }
}
I'd like to inject a list of packet handlers into a class that manages packet handling so that it can be extended in the future with additional packet handlers.
public class PacketHandlerManager
{
public PacketHandlerManager(IEnumerable<IPacketHandler<IPacket>> packetHandlers)
{
}
}
The trouble I'm having is when creating the injected parameter. I cannot do
var packetHandlers = new List<IPacketHandler<IPacket>>
{
new FooPacketHandler(),
new BarPacketHandler()
};
because I cannot create an instance like so:
IPacketHandler<IPacket> packetHandler = new FooPacketHandler();
I get the error Cannot implicitly convert type 'FooPacketHandler' to 'IPacketHandler<IPacket>. An explicit conversion exists (are you missing a cast?)
I had a look at a similar question: Casting generic type with interface constraint. In that question, OP didn't show the members of the interface, only the definition of it from a generics point of view. From what I can see, if my interface didn't use the generic type parameter as an input, I could make it covariant using the out keyword, but that doesn't apply here.
How do I achieve making manager adhere to the open-closed principle? Is my only recourse changing the interface definition to
public interface IPacketHandler
{
void HandlePacket(IPacket packet);
}
and then casting to a particular packet in the implementation?
The core of the issue is that ultimately you would call your handler passing a concrete packet (of a concrete type) to it as an argument, even though you hide the argument behind IPacket.
Somehow then, trying to call the HandlePacket( FooPacket ) with BarPacket argument would have to fail, the only question is when/where it fails.
As you already noticed, introducing the generic parameter to the packet handler makes it fail in the compile time and there is no easy workaround over it.
Your idea to drop the generic parameter, i.e. to have
public interface IPacketHandler
{
void HandlePacket(IPacket packet);
}
is a possible solution. It however pushes the possible failure to the runtime, where you now have to check if a handler is called with inappropriate argument.
What you could also do is to make this runtime check more explicit by introducing a contract for it:
public interface IPacketHandler
{
bool CanHandlePacket(IPacket packet);
void HandlePacket(IPacket packet);
}
This makes it cleaner for the consumer to safely call HandlePacket - assuming they get a positive result from calling CanHandlePacket before.
For example, a possible naive loop over a list of packets and calling your handlers would become
foreach ( var packet in _packets )
foreach ( var handler in _handlers )
if ( handler.CanHandlePacket(packet) )
handler.HandlePacket(packet);
You can solve this with a little bit of reflection.
Firstly, for convenience (and to help slightly with type-safety), introduce a "Tag" interface which all your IPacketHandler<T> interfaces will implement:
public interface IPacketHandlerTag // "Tag" interface.
{
}
This is not really necessary, but it means you can use IEnumerable<IPacketHandlerTag> instead of IEnumerable<object> later on, which does make things a little more obvious.
Then your IPacketHandler<T> interface becomes:
public interface IPacketHandler<in T> : IPacketHandlerTag where T : IPacket
{
void HandlePacket(T packet);
}
Now you can write a PacketHandlerManager that uses reflection to pick out the method to use to handle a packet, and add it to a dictionary like so:
public class PacketHandlerManager
{
public PacketHandlerManager(IEnumerable<IPacketHandlerTag> packetHandlers)
{
foreach (var packetHandler in packetHandlers)
{
bool appropriateMethodFound = false;
var handlerType = packetHandler.GetType();
var allMethods = handlerType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
foreach (var method in allMethods.Where(m => m.Name == "HandlePacket"))
{
var args = method.GetParameters();
if (args.Length == 1 && typeof(IPacket).IsAssignableFrom(args[0].ParameterType))
{
_handlers.Add(args[0].ParameterType, item => method.Invoke(packetHandler, new object[]{item}));
appropriateMethodFound = true;
}
}
if (!appropriateMethodFound)
throw new InvalidOperationException("No appropriate HandlePacket() method found for type " + handlerType.FullName);
}
}
public void HandlePacket(IPacket packet)
{
if (_handlers.TryGetValue(packet.GetType(), out var handler))
{
handler(packet);
}
else
{
Console.WriteLine("No handler found for packet type " + packet.GetType().FullName);
}
}
readonly Dictionary<Type, Action<IPacket>> _handlers = new Dictionary<Type, Action<IPacket>>();
}
If a packet handler passed to the PacketHandlerManager constructor does not implement a method called HandlePacket with a single argument that is assignable from IPacket, it will throw an InvalidOperationException.
For example, attempting to use an instance of the following class would cause the constructor to throw:
public class BadPacketHandler: IPacketHandlerTag
{
public void HandlePacket(string packet)
{
Console.WriteLine("Handling string");
}
}
Now you can call use it thusly:
var packetHandlers = new List<IPacketHandlerTag>
{
new FooPacketHandler(),
new BarPacketHandler()
};
var manager = new PacketHandlerManager(packetHandlers);
var foo = new FooPacket();
var bar = new BarPacket();
var baz = new BazPacket();
manager.HandlePacket(foo);
manager.HandlePacket(bar);
manager.HandlePacket(baz);
Putting it all together into a compilable console app:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace ConsoleApp1
{
public interface IPacket
{
int Size { get; }
}
public class FooPacket : IPacket
{
public int Size => 10;
public string FooProperty { get; set; }
}
public class BarPacket : IPacket
{
public int Size => 20;
public string BarProperty { get; set; }
}
public class BazPacket : IPacket
{
public int Size => 20;
public string BazProperty { get; set; }
}
public interface IPacketHandlerTag // "Tag" interface.
{
}
public interface IPacketHandler<in T> : IPacketHandlerTag where T : IPacket
{
void HandlePacket(T packet);
}
public class FooPacketHandler : IPacketHandler<FooPacket>
{
public void HandlePacket(FooPacket packet)
{
Console.WriteLine("Handling FooPacket");
}
}
public class BarPacketHandler : IPacketHandler<BarPacket>
{
public void HandlePacket(BarPacket packet)
{
Console.WriteLine("Handling BarPacket");
}
}
public class PacketHandlerManager
{
public PacketHandlerManager(IEnumerable<IPacketHandlerTag> packetHandlers)
{
foreach (var packetHandler in packetHandlers)
{
bool appropriateMethodFound = false;
var handlerType = packetHandler.GetType();
var allMethods = handlerType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
foreach (var method in allMethods.Where(m => m.Name == "HandlePacket"))
{
var args = method.GetParameters();
if (args.Length == 1 && typeof(IPacket).IsAssignableFrom(args[0].ParameterType))
{
_handlers.Add(args[0].ParameterType, item => method.Invoke(packetHandler, new object[]{item}));
appropriateMethodFound = true;
}
}
if (!appropriateMethodFound)
throw new InvalidOperationException("No appropriate HandlePacket() method found for type " + handlerType.FullName);
}
}
public void HandlePacket(IPacket packet)
{
if (_handlers.TryGetValue(packet.GetType(), out var handler))
{
handler(packet);
}
else
{
Console.WriteLine("No handler found for packet type " + packet.GetType().FullName);
}
}
readonly Dictionary<Type, Action<IPacket>> _handlers = new Dictionary<Type, Action<IPacket>>();
}
class Program
{
public static void Main()
{
var packetHandlers = new List<IPacketHandlerTag>
{
new FooPacketHandler(),
new BarPacketHandler()
};
var manager = new PacketHandlerManager(packetHandlers);
var foo = new FooPacket();
var bar = new BarPacket();
var baz = new BazPacket();
manager.HandlePacket(foo);
manager.HandlePacket(bar);
manager.HandlePacket(baz);
}
}
}
The output of this is:
Handling FooPacket
Handling BarPacket
No handler found for packet type ConsoleApp1.BazPacket
Thanks for the answers. The solution I ended up with is this, starting with the library code:
public enum PacketType
{
Foo,
Bar
}
public interface IPacket
{
PacketType Type { get; }
}
public class FooPacket : IPacket
{
public PacketType Type => PacketType.Foo;
public string FooProperty { get; }
}
public class BarPacket : IPacket
{
public PacketType Type => PacketType.Bar;
public string BarProperty { get; }
}
The above version is a better approximation of the real thing.
public interface IPacketHandler
{
void HandlePacket(IPacket packet);
}
public abstract class PacketHandler<T> : IPacketHandler where T : IPacket
{
public abstract PacketType HandlesPacketType { get; }
public void HandlePacket(IPacket packet)
{
if (packet is T concretePacket)
{
HandlePacket(concretePacket);
}
}
protected abstract void HandlePacket(T packet);
}
public class FooPacketHandler : PacketHandler<FooPacket>
{
public override PacketType HandlesPacketType => PacketType.Foo;
protected override void HandlePacket(FooPacket packet) { /* some logic that accesses FooProperty */ }
}
public class BarPacketHandler : PacketHandler<BarPacket>
{
public override PacketType HandlesPacketType => PacketType.Bar;
protected override void HandlePacket(BarPacket packet) { /* some logic that accesses BarProperty */ }
}
public class PacketHandlerManager
{
public PacketHandlerManager(Library library, IEnumerable<IPacketHandler> packetHandlers)
{
foreach (var packetHandler in packetHandlers)
{
library.Bind(packetHandler.HandlesPacketType, packetHandler.HandlePacket);
}
}
}
There's some more logic in PacketHandlerManager which I've omitted here. library dispatches packets to handlers, so I don't have to deal with that explicitly after I register handlers using the Bind method.
It's not exactly what I imagined, but it'll do.

must implement EITHER interface A OR interface B (exactly one)

I have an interface that looks like this:
public interface IOpportunity
{
string Name { get; }
string Description { get; }
ILocation Location { get; }
}
public interface ILocation : IHierarchicalEntity
{
int OpptyCount { get; }
}
public interface IHierarchicalEntity
{
string SID { get; }
string Name { get; }
}
However, I want the ILocation object to also implement ONE of these interfaces:
public interface IHierarchicalEntityWithParentNames : IHierarchicalEntity
{
/// <summary>
/// Returns the lowest level that this heirarchy goes (0 for a flat hierarchy, 1 for a two-level etc.)
/// </summary>
int LeafLevel { get; }
/// <summary>
/// Returns the name of the Segment for the given level (0 for a root node, n for leaf node, where n = LeafLevel)
/// </summary>
/// <param name="level"></param>
/// <returns></returns>
string GetNameForLevel(int level);
}
public interface IHierarchicalEntityWithParentIds : IHierarchicalEntity
{
IHierarchicalEntityWithParentIds ParentEntity { get; }
string ParentSID { get; }
}
Due to the nature of the code I am writing, I cannot combine these interfaces into one interface that has some sort of GetParent method
In the code that consumes these interfaces, I have two classes - one that consumes the ILocation object if it is an IHierarchicalEntityWithParentNames and another if it is an IHierarchicalEntityWithParentIds
How would I lay out the interfaces (perhaps I have to have some abstract classes) to support having this "one or the other" design?
You can't. You either explicitly implement an interface, or you don't. What you're describing is effectively "either method A or method B will exist," but that's not a concept that exists in C# (or any other language that I'm aware of!).
The closest you'll be able to get would be to throw an exception in the code that consumes your interface if the class doesn't also implement one of the other two interfaces.
Alternatively, I imagine you could have a base class whose constructor will throw an exception if it doesn't also implement one or other of the interfaces. This would give you an earlier check, but it's still a runtime check and, personally, I think it's a horrible idea.
I believe you are over-constraining the true problem. This is very similar to an issue I encountered in my game engine, where coordinates on a hex grid can be either in the canonical reference frame (axes at 120 degress, convenient for most internal game functions) or in the rectangular (user) reference frame with axes at 90 degrees (convenient for most user-visiable game functions).
I addressed this by buidlng a single class Coords that explicitly implements both interfaces ICoordsCanon and ICoordsUser. The actual coordinates are lazily stored and evaluated with an automated conversion like this:
protected static IntMatrix2D MatrixUserToCanon;
protected IntVector2D VectorCanon {
get { return ! isCanonNull ? _vectorCanon
: VectorUser * MatrixUserToCanon; }
set { _vectorCanon = value; isUserNull = true; }
} IntVector2D _vectorCanon;
bool isCanonNull;
protected static IntMatrix2D MatrixCanonToUser;
protected IntVector2D VectorUser {
get { return ! isUserNull ? _vectorUser
: VectorCanon * MatrixCanonToUser; }
set { _vectorUser = value; isCanonNull = true; }
} IntVector2D _vectorUser;
bool isUserNull;
The constructor for Coords is private, with public static functions NewUserCoords(...) and NewCanonCoords(...) defined.
Alhough the implementation is not truly either ... or ..., it APPEARS to be implemented so to the application. Most application usages either works with ICoordsCanon objects, or with ICoordsUser objects; the two methods ICoordsCanon.User() and ICoordsUser.Canon() exist for converting between the two as necessary.
By popular demand, here are the interface definitions and implementations.
public interface ICoordsUser {
int X { get; }
int Y { get; }
IntVector2D Vector { get; set; }
ICoordsCanon Canon { get; }
//ICoordsUser Clone();
string ToString();
int Range(ICoordsUser coords);
IEnumerable<NeighbourCoords> GetNeighbours(Hexside hexsides);
}
public partial class Coords {
int ICoordsUser.X { get { return VectorUser.X; } }
int ICoordsUser.Y { get { return VectorUser.Y; } }
IntVector2D ICoordsUser.Vector { get { return VectorUser; }
set { VectorUser=value; } }
ICoordsCanon ICoordsUser.Canon { get { return this; } }
//ICoordsUser ICoordsUser.Clone() { return NewUserCoords(VectorUser); }
string ICoordsUser.ToString() { return VectorUser.ToString(); }
IEnumerable<NeighbourCoords> ICoordsUser.GetNeighbours(Hexside hexsides) {
return GetNeighbours(hexsides);
}
int ICoordsUser.Range(ICoordsUser coords) { return Range(coords.Canon); }
}
}
and
public interface ICoordsCanon {
int X { get; }
int Y { get; }
IntVector2D Vector { get; set; }
ICoordsCustom Custom { get; }
ICoordsUser User { get; }
//ICoordsCanon Clone();
string ToString();
int Range(ICoordsCanon coords);
IEnumerable<NeighbourCoords> GetNeighbours(Hexside hexsides);
}
public partial class Coords {
int ICoordsCanon.X { get { return VectorCanon.X; } }
int ICoordsCanon.Y { get { return VectorCanon.Y; } }
IntVector2D ICoordsCanon.Vector { get { return VectorCanon; }
set { VectorCanon=value; } }
ICoordsUser ICoordsCanon.User { get { return this; } }
ICoordsCustom ICoordsCanon.Custom { get { return this; } }
//ICoordsCanon ICoordsCanon.Clone() { return NewCanonCoords(this.VectorCanon); }
string ICoordsCanon.ToString() { return VectorCanon.ToString(); }
IEnumerable<NeighbourCoords> ICoordsCanon.GetNeighbours(Hexside hexsides) {
return GetNeighbours(hexsides);
}
int ICoordsCanon.Range(ICoordsCanon coords) { return Range(coords); }
}
Note that I have not included the entire definition of class Coords, as that would simply be far too large a post. The entire implementation is availabel on CodePlex here: HexGrid Utilities
I am not aware of any way to enforce this at compile time. I think you would have to make this a runtime check by using a base class that throws an exception if both interfaces are implemented.
However, that won't stop someone from bypassing your base class and implementing the interfaces themselves, and I know of no way to prevent that.
You can try Code Contracts. Post-condition. Smth like this
[ContractClassFor(typeof(IOpportunity))]
public abstract class OpportunityContract : IOpportunity
{
public ILocation Location
{
get { Contract.Ensures(Contract.Result<ILocation>() is IHierarchicalEntityWithParentNames || Contract.Result<ILocation>() is IHierarchicalEntityWithParentIds); }
}
}

Encapsulating Action<T> and Func<T>?

I'm trying to make a design for some sort of IExecutable interface. I will not get into details, but the point is that I have several Actions that need to be executed from a base class. They may take different parameters (no big deal), and they may/may not return a value.
So far, this is my design:
public abstract class ActionBase
{
// ... snip ...
}
public abstract class ActionWithResultBase<T>: ActionBase
{
public abstract T Execute();
}
public abstract class ActionWithoutResultBase: ActionBase
{
public abstract void Execute();
}
So far, each of my concrete actions need to be a child from either ActionWithResultBase or ActionWithoutResult base, but I really don't like that. If I could move the definition of Execute to ActionBase, considering that the concrete class may or may not return a value, I will have achieved my goal.
Someone told me this could be done with using Func and Action, for which I totally agree, but I can't find a way to have that into one single class so that the caller would know if the action is going to return a value or not.
Brief: I want to do something like:
// Action1.Execute() returns something.
var a = new Action1();
var result = a.Execute();
// Action2.Execute() returns nothing.
var b = new Action2();
b.Execute();
If you want a lightweight solution, then the easiest option would be to write two concrete classes. One will contain a property of type Action and the other a property of type Func<T>:
public class ActionWithResult<T> : ActionBase {
public Func<T> Action { get; set; }
}
public class ActionWithoutResult : ActionBase {
public Action Action { get; set; }
}
Then you can construct the two types like this:
var a1 = new ActionWithResult<int> {
CanExecute = true,
Action = () => {
Console.WriteLine("hello!");
return 10;
}
}
If you don't want to make Action property read/write, then you could pass the action delegate as an argument to the constructor and make the property readonly.
The fact that C# needs two different delegates to represent functions and actions is quite annoying. One workaround that people use is to define a type Unit that represents "no return value" and use it instead of void. Then your type would be just Func<T> and you could use Func<Unit> instead of Action. The Unit type could look like this:
public class Unit {
public static Unit Value { get { return null; } }
}
To create a Func<Unit> value, you'll write:
Func<Unit> f = () => { /* ... */ return Unit.Value; }
The following interfaces should do the trick -- it's essentially copying the Nullable pattern
public interface IActionBase
{
bool HasResult { get; }
void Execute() { }
object Result { get; }
}
public interface IActionBase<T> : IActionBase
{
new T Result { get; }
}
public sealed class ActionWithReturnValue<T> : IActionBase<T>
{
public ActionWithReturnValue(Func<T> action) { _action = action; }
private Func<T> _action;
public bool HasResult { get; private set; }
object IActionBase.Result { get { return this.Result; } }
public T Result { get; private set; }
public void Execute()
{
HasResult = false;
Result = default(T);
try
{
Result = _action();
HasResult = true;
}
catch
{
HasResult = false;
Result = default(T);
}
}
}
public sealed class ActionWithoutReturnValue : IActionBase
{
public bool HasResult { get { return false; } }
object IActionBase.Result { get { return null; } }
public void Execute() { //... }
}
You know that you can ignore the return value of a method right? You don't have to use it.
what about something simple:
public class ActionExecuter
{
private MulticastDelegate del;
public ActionExecuter(MulticastDelegate del)
{
this.del = del;
}
public object Execute(params object[] p)
{
return del.DynamicInvoke(p);
}
}

Categories

Resources