C# 要求接口实现具有静态解析方法

C# 要求接口实现具有静态解析方法,c#,interface,static,C#,Interface,Static,我有一个最小的接口,将处理一组对象,这些对象的类实现了这个接口。集合(及其相关功能)不关心这些对象名称以外的任何细节、将它们转换为XML的能力以及从XML解析它们的能力 接口的未来实现将对集合的元素做更多的工作,并且显然将实现它们自己的Parse和ToXml方法(集合将在遇到这些项时使用这些方法来适当地解析这些项) 不幸的是,我无法在接口中列出静态解析方法(我已经读过)。让解析方法需要实例对我来说没有意义。有没有办法要求接口的所有实现都有一个静态解析方法 public interface IFo

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

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

不幸的是,我无法在接口中列出静态解析方法(我已经读过)。让解析方法需要实例对我来说没有意义。有没有办法要求接口的所有实现都有一个静态解析方法

public interface IFoo
{
  string Name { get; }

  string ToXml();

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

你不能那样做。而且静态方法也不是多态的,所以它没有太多意义


这里需要的是某种工厂模式。

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

您可以使用工厂模式实现类似的行为,并要求实现
IFoo
的类引用该工厂(可以通过构造函数注入将其注入):


假设
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);
}
也许是这样

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
}

即使以上是一个解决方案,我也鼓励您使用Abstract工厂和/或模板方法。请看。另一种选择可能是使用,如果您不想在多个实现中共享它。

广义上说,我(有时)知道会对以下内容使用扩展方法:

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/>";
    }
}
还有一个测试:

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");
}
publicstatict解析(
这个字符串是xml,
Func usememe=null)
T:IFoo在哪里
{
if(usemome==null)
usemome=(x=>newfoo(x));
返回(T)UseMome(“derp”);
}
唉,当我们偏离“规范”时,我们现在必须告诉方法我们想要什么:

var aFoo=“some xml.Parse();
Console.WriteLine(aFoo.ToXml());
var aBar=“some xml”.Parse(s=>newbar);
Console.WriteLine(aBar.ToXml());

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

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. */ }

我已经考虑过了,但在子类中重写正是我们所需要的。@Jim因为您不使用实例来调用静态方法,所以重写它们没有意义,只需在需要的每个类中编写它们。@Jim:静态方法无论如何都不起作用。您不能重写静态方法。@wRAR这是我们的计划,但大多数实现类将不会由我们编写。有没有办法确保它们中的每一个都有一个静态解析方法?或者我们只需要相信实现该类的人就可以完成它吗?要求他们包含一个工厂类,提供一种从XML创建“IFoo”实例的方法怎么样?我已经用这样的解决方案更新了我的答案。为什么您希望它是一个静态实现?Static是指不同实现之间的共享方法(不依赖于当前对象,只依赖于其他Static),但是接口应该告诉derrive类需要实现某些东西。我认为“静态”并不是您想要的东西……实现此接口的每个类都需要从XML解析实例,但每个类的解析方式都非常不同。解析本身对于一个特定的类来说是独一无二的……所以“静态”不是你想要的解析方法,我不确定这是否可行;当
公共类栏:IFoo
需要解析某些内容时会发生什么情况?@Jim我同意这不太理想,但对于您的示例,您只需调用“some string”。解析,就像其他人一样……或者我误解了您的问题吗?您对
解析(此字符串xml)
的实现返回了一个新的
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());    
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. */ }