C#中类似模板的实现shim

时间:2013-11-27 00:14:18

标签: c# generics

我发现自己需要这样的东西:

// This could just as well be a concrete class.
//
// It is an interface for the sake of this example.
public interface Quark
{
    void Do();
}

public class Strange : Quark
{
    public virtual void Do()
    {
        // Something is done
    }

    public void DoSpecificThing()
    {
        MessageBox.Show("Specific Thing!");
    }
}

public class Charm : Quark
{
    public virtual void Do()
    {
        // Something else is done
    }

    public void DoAnotherSpecificThing()
    {
        MessageBox.Show("Another Specific Thing!");
    }
}

在另一个档案中:

internal class ReUsableCode<BaseType> : BaseType // <- not allowed
{
    public override void Do()
    {
        // Let's pretend this is around 2000 lines of
        // 90's-style Win32 message spaghetti.

        MessageBox.Show(base.GetType().ToString() + " did!");

        base.Do();
    }
}

public class LibraryStrange : ReUsableCode<Strange>
{
}

public class LibraryCharm : ReUsableCode<Charm>
{
}

在某个地方的某个功能中:

LibraryStrange imStrange = new LibraryStrange();
LibraryCharm imCharmed = new LibraryCharm();

imStrange.Do();
imStrange.DoSpecificThing();

imCharmed.Do();
imCharmed.DoAnotherSpecificThing();

在C ++中,我只是制作一个完全符合上述要求的模板。

由于上述原因,这在C#中是不可能的,并且也不允许多重继承。那么,如果没有复制和粘贴,或者强制一切都从单个基类继承,如何重用词法上相同的实现呢?

这是为了减少所有用户控件库所需的维护工作,这些控件全部继承自System.Windows.Forms中的内容,并以完全相同的方式覆盖WndProc(代码全部被复制和粘贴,而我正试图消除或集中它。)

注意:我没有做大量的C#工作,所以请原谅我,如果这个问题看似基本或滥用这个领域的术语。

2 个答案:

答案 0 :(得分:2)

您可以使用扩展方法进行排序。

public static class ExtensionMethods {

    public static void Do(this ICommon obj, String someArg) {
        Console.WriteLine( obj.GetType().Name +  " foobar " + someArg );
    }
}
public interface ICommon {} // interface doesn't do anything

public class Strange : ICommon {

}
public class Charm : ICommon {

}

public static class Program {

    public static void Main(String[] args) {

        Strange quark = new Strange();
        Charm rom = new Charm();
        quark.Do("blargh");
        rom.Do("blargh");
    }
}

答案 1 :(得分:2)

我提出的最简单的解决方案是放弃继承,转而使用合成。不幸的是,它需要概括“SpecificThing”概念。

问题恰恰在于SRPISP在您的设计中受到侵犯,而您提出的所有内容都只是为了避免问题而不是解决问题! / p>

你在评论中写下“基本类型”有问题[...] - 并且把它放在引号中是好的 - 这些不应该是基类型。然而,这个公式过于笼统,很难明确指出什么是错的 - 这里的一切似乎都是错误的。

public interface Quark
{
    void Do();
}

public interface SpecificQuark : Quark
{
    void DoSpecificThing();
}

public class Strange : SpecificQuark
{
    public virtual void Do()
    {
        // Something is done
    }

    public void DoSpecificThing()
    {
        Console.WriteLine("Specific Thing!");
    }
}

public class Charm : SpecificQuark
{
    public virtual void Do()
    {
        // Something else is done
    }

    public void DoSpecificThing()
    {
        Console.WriteLine("Another Specific Thing!");
    }
}

class ReUsableCode<T>
    where T: SpecificQuark, new()
{
    public T InnerQuark { get; private set; }

    public ReUsableCode()
    {
        this.InnerQuark = new T();
    }

    public void Do()
    {
        // Let's pretend this is around 2000 lines of
        // 90's-style Win32 message spaghetti.

        Console.WriteLine(InnerQuark.GetType().ToString() + " did!");
        this.InnerQuark.Do();
    }
}

class LibraryStrange : ReUsableCode<Strange>
{
}

class LibraryCharm : ReUsableCode<Charm>
{
}

然后:

LibraryStrange ls = new LibraryStrange();
LibraryCharm lc = new LibraryCharm();

ls.Do();
ls.InnerQuark.DoSpecificThing();
lc.Do();
lc.InnerQuark.DoSpecificThing();