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.
Tried your code, but even simple calls did not work out of box. Main problem is that MyClass contains unknown element type 'myEement' - that type cannot be deduced from function call parameters. However - if you make a generalization and omit object type - your sample will work in out of box manner:
What is up to myEement (or you probably meant myElement) - you can get's it's type at run-time if necessary.
However - reflection always might slow down your execution. If you don't intend to create super heavy class hierarchy with huge amount of instances - then this should be sufficient for your needs.
Usually, policies should not contain data. For example,
If you would like to combine policies and data then you may consider different interface
Or combination of these two concepts
Usage: