要求接口实现具有静态Parse方法

时间:2013-03-20 14:59:16

标签: c# interface static

我有一个最小的接口,并将处理其类实现此接口的对象的集合。该集合(及其相关功能)不关心这些对象的名称之外的任何细节,将它们转换为XML的能力,以及从XML解析它们的能力。

接口的未来实现将对集合的元素做更多的工作,并且显然会实现自己的Parse和ToXml方法(当遇到这些方法时,集合将使用它们来适当地解析这些项​​目。)

不幸的是,我无法在界面中列出静态Parse方法(我已阅读these three questions)。让Parse方法需要一个实例对我来说没有意义。有没有办法要求接口的所有实现都有静态Parse方法?

public interface IFoo
{
  string Name { get; }

  string ToXml();

  static IFoo Parse(string xml); // Not allowed - any alternatives?
}

6 个答案:

答案 0 :(得分:5)

你做不到。而静态方法无论如何都不是多态的,所以它没有多大意义。

你想要的是某种工厂模式。

答案 1 :(得分:2)

假设Parse接受一个字符串并将其转换为一个完全填充的对象,那么Hydrate方法如何改为:

interface IFoo {
    string Name { get; set; }
    int Age { get; set; }
    void Hydrate(string xml);
}

class Foo : IFoo {
    public string Name { get; set; }
    public int Age { get; set; }

    public void Hydrate(string xml) {
        var xmlReader = ...etc...;
        Name = xmlReader.Read(...whatever...);
        ...etc...;
        Age = xmlReader.Read(...whatever...);
    }
}

void Main() {
    IFoo f = new Foo();
    f.Hydrate(someXml);
}

或稍微流利一点:

public IFoo Hydrate(string xml) {
    // do the same stuff
    return this;
}

void Main() {
    IFoo f = new Foo().Hydrate(someXml);
}

答案 2 :(得分:1)

我想到的唯一选择是在这里使用抽象类而不是接口。但是,无论如何,您将无法在子类中覆盖静态方法的行为。

您可以使用Factory模式实现某种类似的行为,并要求实现IFoo的类具有对该Factory的引用(可以通过构造函数注入将其注入其中):

public interface IFoo
{
    string Name { get; }

    string ToXml();

    IFooFactory FooFactory { get; }
}

public interface IFooFactory
{
    IFoo Parse(string xml);
}

答案 3 :(得分:1)

我会将所有与序列化相关的方法提取到不同的接口中。请考虑以下示例:

public interface IFoo
{
    string Name { get; }
    IFooSerializer GetSerializer(string format);
}

public enum FooSerializerFormat { Xml, Json };

public interface IFooSerializer
{
    string Serialize(IFoo foo);
    IFoo Deserialize(string xml);
}

public class Foo : IFoo
{
    public string Name { get; }

    public IFooSerializer GetSerializer(FooSerializerFormat format)
    {
        case FooSerializerFormat.Xml:
            return new FooXmlSerializer();

        case FooSerializerFormat.Json:
            return new FooJsonSerializer();
    }
}

public class FooXmlSerializer : IFooSerializer { /* Code omitted. */ }
public class FooJsonSerializer : IFooSerializer { /* Code omitted. */ }

答案 4 :(得分:0)

也许这样?

public interface IFoo
{
  string Name { get; }

  string ToXml();

  IFoo Parse(string xml);
}

public abstract class AFoo : IFoo
{
  public string Name { get; set; }

  public string ToXml() { };

  public IFoo Parse(string xml) { return AFoo.StaticParse(xml); };

  public static IFoo StaticParse(string xml) { };  // implement one here
}

即使以上可能是一个解决方案,我也鼓励您使用抽象工厂和/或模板方法。请改为Template Method Pattern。如果您不想在多个实现中共享它,则另一个选项可能是使用Extension method

答案 5 :(得分:0)

从广义上讲,我(有时)已经知道对这样的东西使用扩展方法:

public interface IFoo
{
    string Name {get;}
    string ToXml();    
}

public class Foo : IFoo
{
    public Foo(string name)
    {
        Name = name;
    }
    public string Name {get; private set;}
    public string ToXml()
    {
        return "<derp/>";
    }
}

这就是实例的东西,让我们处理“静态”位:

public static class FooExts
{
    public static IFoo Parse(this string xml)
    {
        return new Foo("derp");
    }
}

测试:

void Main()
{
    var aFoo = "some xml".Parse();
    Console.WriteLine(aFoo.ToXml());
}

正如@Jim所提到的那样,在某种情况下你不会想要一个Foo,在这种情况下你可能会使用类似的东西:

public static T Parse<T>(
    this string xml, 
    Func<string, IFoo> useMeUseMe = null) 
    where T:IFoo
{
    if(useMeUseMe == null)
        useMeUseMe = (x => new Foo(x));
    return (T)useMeUseMe("derp");
}
唉,我们现在必须告诉方法,当我们偏离“规范”时我们想要什么:

var aFoo = "some xml".Parse<Foo>();
Console.WriteLine(aFoo.ToXml());    
var aBar = "some xml".Parse<Bar>(s => new Bar(s));
Console.WriteLine(aBar.ToXml());