Cross reference generic type C# - c#

I'm trying to create some state machines for the little game I'm making with Unity.
I started with some enums, but as I want to do some multi layer state machines, it's not really a good way.
Looking around the internet, I found some interesting ideas, and I came to this kind of implementation
public interface IStateMachine
{
public BaseState CurrentState { get; set; }
}
public abstract class BaseState
{
private IStateMachine _ctx;
// ... other state stuffs
}
That I'm trying to adapt to use a generic type for the context, like this
public abstract class BaseState<T> where T: IStateMachine
{
private T _ctx;
// ... other state stuffs
}
But that won't compile, saying that I forgot a <T> to BaseState<T> CurrentState in my first interface.
Using the generic type BaseState need 1 type arguments
But how could I tell him that T is the class that implements my interface ?
I tried some stuff, like adding a generic to my interface
public interface IStateMachine<T> where T : IStateMachine<T>
{
public BaseState<T> CurrentState { get; set; }
}
but it simply tell me
The type 'T' cannot be used as type parameter 'T' in the generic type or method 'BaseState'. There is no implicit reference conversion from 'T' to 'IStateMachine'.
I'm probably missing a simple fact about generics, and this question might be a duplicate of this question (state machine, unity, but from 7 years ago).

The problem is probably that you do not declare the type when you make the actual state implementation:
public class StateMachine : IStateMachine
...
public class StateA : BaseState<StateMachine > // need to specify T
public class StateB<T>: BaseState<T> where T : IStateMachine // let caller specify T
But the problem you will run into is that you have to declare all the methods and properties you want to use on the common base type. States need to reference each other, so you will need to use the base type in these references. So you will not really gain anything by using generics.
A workaround for this is to use the Curiously recurring template pattern. i.e.
public abstract class BaseState<T> where T: BaseState<T>{
public T Next {get;}
This essentially gives a way to promise that the entire graph of states will have a common type. This can still allow for methods that do things like traversing the graph, without any need to know the actual type, for example:
public static T NextNext<T>(BaseState<T> start) where T : BaseState<T>{
return start.Next.Next;
}
public class MyState : BaseState<MyState>{
...
}
var myState = new MyState(...);
MyState nn = myState.NextNext(); // Keep the type when traversing the graph

The CurrentState Property inside the IStateMachine probably references to the BaseState which needs a generic type. Either way your structure seem a bit tough because it kind of has a recursive link. IStateMachine needs a BaseState but a BaseState needs a IStateMachine?
I would suggest not trying to let the BaseState know what StateMachine it is attached to.
Another suggestion would be to create another Class "StateMachineContext" which the BaseState has a reference to and this StateMachineContext has a reference to IStateMachine.
Yet another approach would be to have it similiar to the following code:
public interface IStateMachine
{
public BaseState CurrentState { get; set; }
}
public abstract class BaseState
{
// Some functionality that IStateMachine needs access
// to.
}
public abstract class BaseState<T> : BaseState where T : IStateMachine
{
private T _ctx;
// ... other state stuffs
}
Another very simple way to begin a statemachine:
(Instead of providing the Data in the state as a reference you could also pass it as a parameter with whatever function you will call on the state.)
public class Entity
{
public IStateMachine<Entity> StateMachine { get; set; }
}
public interface IStateMachine<T>
{
public BaseState<T> CurrentState { get; set; }
// Some generic state handling functionality
}
public abstract class BaseState<T>
{
private T _ctx;
/*
Some required state handling that will
be called by the entity through the statemachine
*/
}

Related

How to identity which class object is being created in Helper class

I am having a abstract class which is being inherited by 2 classes. How can I find out which class is being created in my helper class.
Abstract Class
public abstract class AbstractClass
{
private IHelper helper{ get; }
public Entity()
{
helper= new MyHelper(this);
}
}
MyHelper.cs
public class MyHelper: IHelper
{
private AbstractClass ABClass{get;}
public EntityDataOperation(AbstractClass abClass)
{
//How can I find out which concrete type it is i.e. ClassA or ClassB
ABClass= abClass;
}
}
ClassA
public class ClassA:AbstractClass
{
public string data= "ClassA";
}
ClassB
public class ClassB:AbstractClass
{
public string data= "ClassB";
}
You can use Reflection but your code and methodology is very questionable:
entity.GetType().Name;
You can also test for the subclasses
if (abClass is ClassA)
// found is ClassA
else if (abClass is ClassB)
// found ClassB
It seems like your question boils down to, "If I have an object, how do I get the type of that object?"
var typeOfTheObject = theObject.GetType();
The problem is that this largely defeats the purpose of strongly typed parameters.
This tells you what you need to know about the type:
public EntityDataOperation(AbstractClass abClass)
^^^
That tells you what the type is. It's AbstractClass. If that's not what you need to know - if you don't care that it's an AbstractClass, then why not change the parameter to object?
Polymorphism literally means "multiple shapes." It means that the when you get an instance of AbstractClass, the actual object could be one of many shapes - many implementations of the class. But by taking a parameter of type AbstractClass, this method says that it doesn't care which type it is. It just interacts with the interface it knows about - the methods and properties of AbstractClass, without knowing or caring what the concrete implementation is.

injecting an generic interface

ok I'm little lost with generics in C#
I have this generic interface
interface IInvoiceStorage<T>
where T : class
{
void Persist(T Invoice);
}
with two classes implementing the interface
public class FacturaStorageForSQLServer:IInvoiceStorage<EVT>
{
public void Persist(EVT Invoice)
{
/*Implementation*/
}
}
public class FacturaStorageForMySQLServer:IInvoiceStorage<EVTFruit>
{
public void Persist(EVTFruit Invoice)
{
/*Implementation*/
}
}
The problem comes when I want to declare this in my service class
public class invoice_service
{
IInvoiceStorage Storage;
public invoice_service(IInvoiceStorage storage)
{
Storage=_storage;
}
}
C# tells me that I have to declare de type of the interface but if I do that then my service class is going to depend from the implementation and not from the interface.
Suggestions??
UPDATE 1:
Sorry If I declare the type the interface is going to depend only from the implementations using that type but what happens if I have two implementations using two different types for example EVT and EVTFruit.
I was thinking to use another interface to establish a relationship between EVT and EVTFruit but they can be two totally different objects so I'm not sure if it is a good idea.
You could change your class a little bit:
public class invoice_service<T> where T : class
{
IInvoiceStorage<T> Storage;
public invoice_service(IInvoiceStorage<T> storage)
{
Storage=_storage;
}
}
Which would allow you to use the interface correctly and keep it generic.
Depending on your needs, you could also defined non-generic version of that interface:
public interface IInvoiceStorage
{
...
}
And make classes inherit from this interface, too.
public class FacturaStorageForSQLServer : IInvoiceStorage, IInvoiceStorage<EVT>
public class FacturaStorageForMySQLServer : IInvoiceStorage, IInvoiceStorage<EVTFruit>
That way you can use non-generic version of interface in invoice_service class.
But, as I said, depending on your needs if you can make functionality of that interface independent of type (for example, List<T> also implements IList for list functionalities, without type).
After trying your suggestions and reading some blogs here is what I did and is fulfilling my requeriments at least for now. The problem was resolved when I realized that I shouldn't use the generic repository pattern as a repository itself but as a helper of the repository! At the end what I'm doing is wrapping the generic interfaces inside of another layer of non-generic interfaces.
a Service class calling for an IInvoiceRepositoryService implementation
public class InvoiceService
{
private IInvoiceRepositoryService RepositoryService;
public SQLInvoiceService(IInvoiceRepositoryService _RS)
{
RepositoryService=_RS;
}
}
and their respective implementation for EVT and EVTFruit.
public class EVTRepository:IInvoiceRepositoryService
{
private IInvoiceStorage<EVT> EVTStorage;
public EVTInvoiceRepository(IInvoice<EVT> _EVT)
{
EVTStorage=_EVT;
}
}
public class EVTStorageForSQLServer: IInvoiceStorage<EVT>
{
/*Implementation*/
}
public class EVTStorageForMySQLServer: IInvoiceStorage<EVT>
{
/*Implementation*/
}
public class EVTFruitRepository:IInvoiceRepositoryService
{
private IInvoiceStorage<EVT> EVTFruitStorage;
public EVTFruitInvoiceRepository(IInvoice<EVTFruit> _EVTFruit)
{
EVTFruitStorage=_EVTFruit;
}
}
public class EVTFruitStorageForSQLServer: IInvoiceStorage<EVTFruit>
{
/*Implementation*/
}
public class EVTFruitStorageForMySQLServer: IInvoiceStorage<EVTFruit>
{
/*Implementation*/
}
At the end this was just a design problem I think. I'm going to mark Ron Beyer's response as the answer because is valid and it was really straightforward

Using 'this' in base constructor?

I'm working on a project that involves a lot of interfacing and inheritance, which are starting to get a little tricky, and now I've run into a problem.
I have an abstract class State which takes in a Game object as a constructor argument. In my Game class's constructor, it takes in a State. The idea is that when inheriting from the abstract base Game class, when calling the base class's constructor, you give it an initial State object. However this State object takes in the same Game that you're creating it in. The code looks like this:
public class PushGame : ManiaGame
{
public PushGame() :
base(GamePlatform.Windows, new PlayState(this), 60)
{
}
}
However this doesn't work. I can only assume because the 'this' keyword is not usable until after the constructor has begun to execute. Trying to use it in your base class's constructor doesn't work, apparently. So what would be my best workaround for this? My plan B is to just remove the State argument from the Game class's constructor and just set the state inside the constructor code afterwards.
Is there an easier, less-intrusive way of doing this?
Clearly the ManiaGame class always uses objects of PlayState type, so you can move the creation at the ManiaGame level:
public class PushGame : ManiaGame
{
public PushGame() : base()
{
}
}
public class ManiaGame
{
PlayState ps;
public ManiaGame() {
ps = new PlayState(this);
}
}
If you want more concrete PlayState classes..
public class PushGame : ManiaGame
{
public PushGame() : base()
{
}
protected override PlayState CreatePlayState()
{
return new PushGamePlayState(this);
}
}
public class ManiaGame
{
PlayState ps;
public ManiaGame() {
ps = CreatePlayState();
}
protected virtual PlayState CreatePlayState()
{
return new PlayState(this);
}
}
public class PlayState
{
public PlayState(ManiaGame mg) {}
}
public class PushGamePlayState : PlayState
{
public PushGamePlayState(ManiaGame mg) : base(mg){}
}
If the State implementation used depends on the concrete Game class, then I would create a new instance of the State inside the constructor of the child Game class (PushGame) and access the State in the base class through the abstract property.
public class PushGame : ManiaGame
{
private readonly PlayState gamePlayState;
public PushGame() : base()
{
gamePlayState = new PlayState(this);
}
protected override State GamePlayState
{
get { return gamePlayState; }
}
}
public abstract class ManiaGame
{
protected abstract State GamePlayState { get; }
}
public class State
{
public State(ManiaGame mg) { }
}
public class PlayState : State
{
public PlayState(ManiaGame mg) : base(mg) { }
}
From the C# Language Specification
An instance constructor initializer cannot access the instance being created. Therefore it is a compile-time error to reference this in an argument expression of the constructor initializer, as is it a compile-time error for an argument expression to reference any instance member through a simple_name.
i.e. this can only be used to reference another constructor in the context of a constructor initializer, as the reference to the current object instance won't be available until the construction is completed.
i.e. this can be only used as a scoping keyword before the constructor executes:
: this("ParameterForAnotherConstructor")
But it is not available as a reference to the class instance, since it has not completed construction
: base(this) // Keyword this is not available in this context
And obviously we can't call any instance methods from the constructor initializer either
: base(GetThis()) // Object reference is required
To solve OP's problem, changes to the base Mania class seems inevitable, given the two-way coupling between PlayState and ManiaGame (or subclasses of ManiaGame, like PushGame). There are many patterns available to decouple tight dependencies like this, such as the Dependency Inversion Principal (i.e. abstract the coupling between the classes), or the Observer pattern - (one of the two classes raises events or allows callbacks to be hooked (e.g. delegates or Actions), allowing the second class to 'observe' state changes without the hard coupling between them.
There is a similar Stack Overflow question, Keyword 'this' (Me) is not available calling the base constructor with a workaround similar to your suggestion.
Does your design differentiate between a game (say backgammon) and a game in progress (a game of backgammon)? If you're trying to mix these two concepts then I would suggest modeling them separately. For example, Backgammon and BackgammonContest.
I've recenly experienced this issue when trying to pass concrete instances of implemented interfaces via this to the base constructor.
To work around it, I simply implemented an abstract method on the base class that fetched the instance I was looking for:
public abstract class BaseClass
{
...
protected abstract IMyInterface GetInterface();
...
}
public class DerivedClass : BaseClass, IMyInterface
{
...
protected override IMyInterface GetInterface()
{
return this;
}
...
}
In my base class code, you can then use GetInterface (or whatever type you need) to obtain the instance:
public abstract class BaseClass
{
public void Foo()
{
GetInterface().DoSomething();
}
}

Contravariance and Entity Framework 4.0: how to specify EntityCollection as IEnumerable?

I have specified a couple of interfaces, which I am implementing as entities using Entity Framework 4. The simplest demonstration code I can come up with is:
public class ConcreteContainer : IContainer
{
public EntityCollection<ConcreteChild> Children { get; set; }
}
public class ConcreteChild : IChild
{
}
public interface IContainer
{
IEnumerable<IChild> Children { get; set; }
}
public interface IChild
{
}
I receive the following compiler error from the above:
'Demo.ConcreteContainer' does
not implement interface member
'Demo.IContainer.Children'.
'Demo.ConcreteContainer.Children'
cannot implement
'Demo.IContainer.Children'
because it does not have the matching
return type of
'System.Collections.Generic.IEnumerable'
My current understanding is that this is because IEnumerable (which is implemented by EntityCollection) is covariant but presumably not contravariant:
This type parameter is covariant. That is, you can use
either the type you specified or any type that is more
derived. For more information about covariance and contravariance,
see Covariance and Contravariance in Generics.
Am I correct, & if so, is there any way I can achieve my goal of specifying the IContainer interface purely in terms of other interfaces rather than using concrete classes?
Or, am I misunderstanding something more fundamental?
The generic variance in .NET 4 is irrelevant here. The implementation of an interface has to match the interface signature exactly in terms of types.
For example, take ICloneable, which looks like this:
public interface ICloneable
{
object Clone();
}
It would be nice to be able to implement it like this:
public class Banana : ICloneable
{
public Banana Clone() // Fails: this doesn't implement the interface
{
...
}
}
... but .NET doesn't allow this. You can sometimes use explicit interface implementation work around this, like so:
public class Banana : ICloneable
{
public Banana Clone()
{
...
}
object ICloneable.Clone()
{
return Clone(); // Delegate to the more strongly-typed method
}
}
However, in your case you can't ever do that. Consider the following code, which would be valid if ConcreteContainer was considered to implement IContainer:
IContainer foo = new ConcreteContainer();
foo.Children = new List<IChild>();
Now your property setter is actually only declared to work with EntityCollection<ConcreteChild>, so it clearly can't work with any IEnumerable<IChild> - in violation of the interface.
As far as I understand, you must implement an interface - you can't assume that a covariant/contra-variant member would be picked up as a substitute.
Even if it was permissible, note that setter for children is an issue. Because it will allow to set property of type EntityCollection<ConcreteChild> with value of any other type such as List<ConcreteChild> or EntityCollection<ConcreteChild2> because both are implementing IEnumerable<IChild>.
In current design, I will implement IContainer privately in ConcreteContainer and check the input value in IEnumerable.Children setter for a compatible type. Another way to approach this design is to have generic interfaces such as:
public interface IContainer<T> where T:IChild
{
IEnumerable<T> Children { get; set; }
}
So you need to implement this interface, right?
public interface IContainer
{
IEnumerable<IChild> Children { get; set; }
}
But in the real class, you want the property to be of type EntityCollection<ConcreteChild>. Here’s how you can do this:
public class ConcreteContainer : IContainer
{
// This is the property that will be seen by code that accesses
// this instance through a variable of this type (ConcreteContainer)
public EntityCollection<ConcreteChild> Children { get; set; }
// This is the property that will be used by code that accesses
// this instance through a variable of the type IContainer
IEnumerable<ConcreteChild> IContainer.Children {
get { return Children; }
set {
var newCollection = new EntityCollection<ConcreteChild>();
foreach (var item in value)
newCollection.Add(item);
Children = newCollection;
}
}
}

Generic method is picking up type of base class

I have the following classes (trimmed to only show the basic structure):
public abstract class BaseModel {
public bool PersistChanges() {
// Context is of type "ObjectContext"
DatabaseHelper.Context.SafelyPersistChanges(this);
}
}
public static class ObjectContextExtensions {
public static bool SafelyPersistChanges<T>(this ObjectContext oc, T obj) {
// Persist the object using a transaction
}
}
[Persistent("LEADS")]
public class Lead : BaseModel {
// Extra properties
}
public class LeadsController : Controller {
public ActionResult Save(Lead lead) {
lead.PersistChanges()
}
}
My Lead class derives from BaseModel, which contains a method to persist the object's changes to the database using a transaction. I implemented the transactional persist with an extension method. The problem is that by passing this to SafelyPersistChanges in my BaseModel class, the generic T on the extension method is set to BaseModel. However, since BaseModel isn't marked as a persistent object (which it cannot be), the ORM framework throws an exception.
Example:
Lead lead = LeadRepository.FindByNumber(2);
lead.SalesmanNumber = 4;
// Calls "ObjectContextExtensions.SafelyPersistChanges<BaseModel>(BaseModel obj)"
// instead of "ObjectContextExtensions.SafelyPersistChanges<Lead>(Lead obj)"
lead.PersistChanges();
The above block raises the following exception:
Cannot create mapping for type 'SalesWeb.Data.BaseModel' without persistent attribute.
Any ideas?
Extension Methods are statically bound at compile time. At the point in which SafelyPersistChanges is called, this is typed as BaseModel and hence your exception. In order to get the behavior you want, you'll either need to do an ugly if statement with lots of casting or force the call to the derived class.
Make PersistChanges an abstract method. Then implement the call in the derived classes with exactly the same code.
public class Lead {
public override bool PersistChanges() {
// Context is of type "ObjectContext"
DatabaseHelper.Context.SafelyPersistChanges(this);
}
}
Now this will properly be Lead
I would have designed this differently, making "public bool PersistChanges()" call a virtual method, that is overridden in each subclass.
So, you want a "single" implementation, that varies against a type known by the caller. Sounds like a job for Generics.
public static bool PersistChanges<T>(this T source)
where T : BaseModel
{
// Context is of type "ObjectContext"
//static property which holds a Context instance is dangerous.
DatabaseHelper.Context.SafelyPersistChanges<T>(source);
}
You could solve this using the curiously recurring template pattern:
// change your code to this
public abstract class BaseModel<TDerived> where TDerived : BaseModel
{
public bool PersistChanges() {
// Context is of type "ObjectContext"
DatabaseHelper.Context.SafelyPersistChanges((TDerived)this);
// ^
// note the cast here: -----------------------|
}
}
public class Lead : BaseModel<Lead> { }
// the rest of your code is unchanged
That would work, but I'd probably just follow the other suggestions and use a virtual method.

Categories