5

最小限のインターフェースがあり、クラスがこのインターフェースを実装するオブジェクトのコレクションを処理します。コレクション(および関連する機能)は、名前以外のこれらのオブジェクトの詳細、XMLに変換する機能、およびXMLからオブジェクトを解析する機能を考慮しません。

インターフェイスの将来の実装は、コレクションの要素でさらに多くのことを行い、明らかに独自のParseメソッドとToXmlメソッドを実装します(これらは、検出されたときにこれらのアイテムを適切に解析するためにコレクションによって使用されます)。

残念ながら、インターフェイスに静的な解析メソッドをリストすることはできません(これらの 3つの 質問を読みました)。Parseメソッドにインスタンスを要求させることは私には意味がありません。インターフェイスのすべての実装に静的なParseメソッドがあることを要求する方法はありますか?

public interface IFoo
{
  string Name { get; }

  string ToXml();

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

6 に答える 6

5

あなたはそれをすることはできません。そして、静的メソッドはとにかく多形ではないので、あまり意味がありません。

ここで必要なのは、ある種のファクトリパターンです。

于 2013-03-20T15:03:07.627 に答える
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);
}
于 2013-03-20T15:11:54.113 に答える
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. */ }
于 2013-03-20T15:27:42.190 に答える
1

私の頭に浮かぶ唯一の代替案は、ここでインターフェイスの代わりに抽象クラスを使用することです。ただし、とにかく子クラスで静的メソッドの動作をオーバーライドすることはできません。

Factory パターンを使用IFooして、実装するクラスにその Factory への参照を要求することで、多少似たような動作を実現できます (コンストラクター注入によってそれらに注入できます)。

public interface IFoo
{
    string Name { get; }

    string ToXml();

    IFooFactory FooFactory { get; }
}

public interface IFooFactory
{
    IFoo Parse(string xml);
}
于 2013-03-20T15:03:44.583 に答える
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
}

上記が解決策である可能性があるとしても、代わりにabstactfactoryおよび/またはtemplateメソッドを使用することをお勧めします。代わりに、テンプレートメソッドパターンを参照してください。複数の実装間で拡張メソッドを共有したくない場合は、拡張メソッドを使用することもできます。

于 2013-03-20T15:13:55.660 に答える
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());    
于 2013-03-20T15:25:38.383 に答える