I'm trying to implement a c++ like template with C# generics and policy pattern based on this answer
This is a sample of the pattern:
interface ISomePolicy<T,U>
{
void _doSomething(U u);
}
class MyClass<T,U>:
ISomePolicy<int, double>,
ISomePolicy<int, int>
{
internal T myElement {get;set;}
public MyClass(T Element) {
myElement = Element;
}
void ISomePolicy<int, double>._doSomething(double u)
{
Console.WriteLine("this is int, double");
}
void ISomePolicy<int, int>._doSomething(int u)
{
Console.WriteLine("this is int, int");
}
}
static class MyClassExtension
{
//What I want to do
public static void doSomething<P, T, U>(this P oTh, U u) where P : MyClass<T, U>, ISomePolicy<T, U>
{
oTh._doSomething(u);
}
}
My intended behaviour is like this:
MyClass<int, double> oClass = new MyClass<int, double>(3);
oClass.doSomething(0.5); //This works
oClass.doSomething(1); //This works
oClass.doSomething("This should fail"); //Breaks at compile time
MyClass<string, double> oClass1 = new MyClass<string, double>("sadfsd"); //Not implemented, wasn't able to prevent the construction.
oClass1.doSomething(0.4); //Breaks at compile time
But so far I wasn't able to make .net accept Generic Extension with less arguments than parameters
I can call the interface explicitly, which is horrible verbose defeating the purpose of all this.
oClass.doSomething < MyClass<int, double>,int,double>(0.5);
I thought of working that around with a wrapper:
static class MyClassExtension{
private static void wrappedDoSomething<P, T, U>(this P oTh, U u)
where P : MyClass<T, U>, ISomePolicy<T, U>
{
oTh._doSomething(u);
}
public static void doSomething<T, U>(this MyClass<T, U> oTh, U u)
{
oTh.wrappedDoSomething<MyClass<T, U>, T, U>(u);
}
}
But the wrapper can't resolve both types for the wrapped function, failing with:
Error 1 The type 'MyClass' cannot be used as type parameter 'P' in the generic type or method 'MyClassExtension.wrappedDoSomething(P, U)'. There is no implicit reference conversion from 'MyClass' to 'ISomePolicy'
Any insights to fix the parameters issue or redesign all this are appreciated.
For context this would be used to wrap I/O translators. T
in my case would be the target I/O format, and U
the object representation of that data used by my framework.
I'm aware that this can be easily achieved with delegates or interfaces, but the objective is that the framework user easily instantiates the desired translation, and if an implementation doesn't exists, it can be trivially added to a common interface.
EDIT: Resolving a generic method from inside another generic method/class neither seems to work on mono.