Implementing multiparameter C++ template like behaviour on C# using Policy Pattern

无人久伴 提交于 2019-12-01 16:22:11

Usually, policies should not contain data. For example,

interface ISomePolicy<T, U>
{
    void _doSomething(T t, U u);
}

struct SomePolicyImplementation :
    ISomePolicy<int, double>,
    ISomePolicy<int, int>,
    ISomePolicy<double, double>
{
    void ISomePolicy<int, int>._doSomething(int t, int u)
        => Console.WriteLine("this is int, int");

    void ISomePolicy<int, double>._doSomething(int t, double u)
        => Console.WriteLine("this is int, double");

    void ISomePolicy<double, double>._doSomething(double t, double u)
        => Console.WriteLine("this is double, double");
}

static class SomePolicyExtension
{
    public static void doSomething<P, T, U>(this P policy, T t, U u)
        where P : struct, ISomePolicy<T, U>
        => policy._doSomething(t, u);
}

If you would like to combine policies and data then you may consider different interface

interface IEmbeddedPolicy<U>
{
    void _doSomething(U u);
}

class MyClass<T> :
    IEmbeddedPolicy<double>,
    IEmbeddedPolicy<int>
{
    public T Value { get; }

    public MyClass(T value) { this.Value = value; }

    void IEmbeddedPolicy<int>._doSomething(int u)
        => Console.WriteLine("this is T, int");

    void IEmbeddedPolicy<double>._doSomething(double u)
        => Console.WriteLine("this is T, double");
}

static class EmbeddedPolicyExtension
{
    public static void doSomething<E, U>(this E embedded, U u)
        where E : IEmbeddedPolicy<U>
        => embedded._doSomething(u);
}

Or combination of these two concepts

class MySuperClass<P, T>:
    IEmbeddedPolicy<double>,
    IEmbeddedPolicy<int>
    where P: struct, ISomePolicy<T, double>, ISomePolicy<T, int>
{
    public T Value { get; }

    public MySuperClass(T value) { this.Value = value; }

    void IEmbeddedPolicy<int>._doSomething(int u)
        => new P()._doSomething(this.Value, u);

    void IEmbeddedPolicy<double>._doSomething(double u)
        => new P()._doSomething(this.Value, u);
}

Usage:

// 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<int>(54);
my.doSomething(5);
my.doSomething(89.7);

// combination
var x = new MySuperClass<SomePolicyImplementation, int>(53);
x.doSomething(9);
x.doSomething(18.3);

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:

using System;
using System.Collections.Generic;

interface ISomePolicy<U> 
{
    void _doSomething(U u);
}

public class MyClass<U> :
     ISomePolicy<double>,
     ISomePolicy<int>
{
    internal object myEement { get; set; }

    public MyClass(object Element)
    {
        myEement = Element;
    }

    void ISomePolicy<double>._doSomething(double u)
    {
        Console.WriteLine("this is double");
    }

    void ISomePolicy<int>._doSomething(int u)
    {
        Console.WriteLine("this is int");
    }
}

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

class Program
{
    static void Main()
    {
        MyClass<double> oClass = new MyClass<double>(3);
        oClass.doSomething(0.5); //This works
        oClass.doSomething(1);   //This works            
        //oClass.doSomething("Will not work");
    }
}

What is up to myEement (or you probably meant myElement) - you can get's it's type at run-time if necessary.

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

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!