使用策略模式在C#上实现多参数C ++模板行为

我正在尝试使用C#generics和基于此答案的策略模式实现类似c ++的模板

这是模式的一个示例:

interface ISomePolicy { void _doSomething(U u); } class MyClass: ISomePolicy, ISomePolicy { internal T myElement {get;set;} public MyClass(T Element) { myElement = Element; } void ISomePolicy._doSomething(double u) { Console.WriteLine("this is int, double"); } void ISomePolicy._doSomething(int u) { Console.WriteLine("this is int, int"); } } static class MyClassExtension { //What I want to do public static void doSomething

(this P oTh, U u) where P : MyClass, ISomePolicy { oTh._doSomething(u); } }

我的预期行为是这样的:

  MyClass oClass = new MyClass(3); oClass.doSomething(0.5); //This works oClass.doSomething(1); //This works oClass.doSomething("This should fail"); //Breaks at compile time MyClass oClass1 = new MyClass("sadfsd"); //Not implemented, wasn't able to prevent the construction. oClass1.doSomething(0.4); //Breaks at compile time 

但到目前为止,我无法使.net接受通用扩展,参数少于参数

我可以明确地调用接口,这是一个可怕的冗长,打败了所有这一切的目的。

 oClass.doSomething < MyClass,int,double>(0.5); 

我想用包装器来解决这个问题:

 static class MyClassExtension{ private static void wrappedDoSomething

(this P oTh, U u) where P : MyClass, ISomePolicy { oTh._doSomething(u); } public static void doSomething(this MyClass oTh, U u) { oTh.wrappedDoSomething<MyClass, T, U>(u); } }

但是包装器无法解析包装函数的两种类型,但失败的是:

错误1类型’MyClass’不能用作generics类型或方法’MyClassExtension.wrappedDoSomething(P,U)’中的类型参数’P’。 没有从“MyClass”到“ISomePolicy”的隐式引用转换

任何有关修复参数问题或重新设计所有这些的见解都表示赞赏。


对于上下文,这将用于包装I / O转换器。 在我的情况下, T将是目标I / O格式, U是我的框架使用的数据的对象表示。

我知道这可以通过委托或接口轻松实现,但目标是框架用户可以轻松实例化所需的转换,如果实现不存在,则可以简单地将其添加到公共接口。


编辑:从另一个generics方法/类内部解析generics方法似乎既不适用于单声道。

通常,策略不应包含数据。 例如,

 interface ISomePolicy { void _doSomething(T t, U u); } struct SomePolicyImplementation : ISomePolicy, ISomePolicy, ISomePolicy { void ISomePolicy._doSomething(int t, int u) => Console.WriteLine("this is int, int"); void ISomePolicy._doSomething(int t, double u) => Console.WriteLine("this is int, double"); void ISomePolicy._doSomething(double t, double u) => Console.WriteLine("this is double, double"); } static class SomePolicyExtension { public static void doSomething(this P policy, T t, U u) where P : struct, ISomePolicy => policy._doSomething(t, u); } 

如果您想要合并策略和数据,那么您可以考虑不同的界面

 interface IEmbeddedPolicy { void _doSomething(U u); } class MyClass : IEmbeddedPolicy, IEmbeddedPolicy { public T Value { get; } public MyClass(T value) { this.Value = value; } void IEmbeddedPolicy._doSomething(int u) => Console.WriteLine("this is T, int"); void IEmbeddedPolicy._doSomething(double u) => Console.WriteLine("this is T, double"); } static class EmbeddedPolicyExtension { public static void doSomething(this E embedded, U u) where E : IEmbeddedPolicy => embedded._doSomething(u); } 

或者这两个概念的组合

 class MySuperClass: IEmbeddedPolicy, IEmbeddedPolicy where P: struct, ISomePolicy, ISomePolicy { public T Value { get; } public MySuperClass(T value) { this.Value = value; } void IEmbeddedPolicy._doSomething(int u) => new P()._doSomething(this.Value, u); void IEmbeddedPolicy._doSomething(double u) => new P()._doSomething(this.Value, u); } 

用法:

 // independent policy var policy = new SomePolicyImplementation(); policy.doSomething(5, 6); policy.doSomething(5, 6.7); policy.doSomething(5.3, 6.7); // embedded policy var my = new MyClass(54); my.doSomething(5); my.doSomething(89.7); // combination var x = new MySuperClass(53); x.doSomething(9); x.doSomething(18.3); 

试过你的代码,但即使是简单的调用都没有开箱即用。 主要问题是MyClass包含未知元素类型’myEement’ – 该类型不能从函数调用参数推导出来。 但是 – 如果进行泛化并省略对象类型 – 您的示例将以开箱即用的方式工作:

 using System; using System.Collections.Generic; interface ISomePolicy { void _doSomething(U u); } public class MyClass : ISomePolicy, ISomePolicy { internal object myEement { get; set; } public MyClass(object Element) { myEement = Element; } void ISomePolicy._doSomething(double u) { Console.WriteLine("this is double"); } void ISomePolicy._doSomething(int u) { Console.WriteLine("this is int"); } } static class MyClassExtension { public static void doSomething(this P oTh, U u) where P : ISomePolicy { oTh._doSomething(u); } } class Program { static void Main() { MyClass oClass = new MyClass(3); oClass.doSomething(0.5); //This works oClass.doSomething(1); //This works //oClass.doSomething("Will not work"); } } 

什么是myEement(或者你可能意味着myElement) – 如果有必要,你可以在运行时获得它的类型。

 myElement.GetType(), or cast to it - eg if( myElement is int ) DoSomethingWithInt( (int) myElement ); 

但是 – reflection总是会降低执行速度。 如果您不打算创建具有大量实例的超重类层次结构 – 那么这应该足以满足您的需求。