要求接口实现具有静态Parse方法
本文关键字:静态 Parse 方法 接口 实现 | 更新日期: 2023-09-27 18:04:58
我得到了一个最小的接口,并且将处理一个对象集合,这些对象的类实现了这个接口。集合(及其相关的功能)不关心这些对象的任何细节,除了它们的名称、将它们转换为XML的能力以及从XML解析它们的能力。
接口的未来实现将对集合的元素做更多的工作,并且显然将实现它们自己的Parse和ToXml方法(集合将在遇到这些项时使用它们来适当地解析这些项)。
不幸的是,我无法在接口中列出静态Parse方法(我已经阅读了这三个问题)。对我来说,让Parse方法需要实例是没有意义的。有没有办法要求接口的所有实现都有一个静态Parse方法?
public interface IFoo
{
string Name { get; }
string ToXml();
static IFoo Parse(string xml); // Not allowed - any alternatives?
}
你不能那样做。而且静态方法不是多态的,所以它不会有太大的意义。
这里你需要的是某种工厂模式
假设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);
}
我想到的唯一替代方法是在这里使用抽象类而不是接口。但是,无论如何,您都无法在子类中重写静态方法的行为。
您可以使用工厂模式实现类似的行为,并要求实现IFoo
的类有对该工厂的引用(可以通过构造函数注入):
public interface IFoo
{
string Name { get; }
string ToXml();
IFooFactory FooFactory { get; }
}
public interface IFooFactory
{
IFoo Parse(string xml);
}
我将把所有与序列化相关的方法提取到不同的接口中。请考虑下面的例子:
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. */ }
也许这样?
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
}
即使上面可能是一个解决方案,我也会鼓励你使用抽象工厂和/或模板方法。请参阅模板方法模式。如果您不想在多个实现中共享扩展方法,另一个选择可能是使用它。
一般来说,我已经知道(偶尔)使用扩展方法做这样的事情:
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/>";
}
}
这就是实例的内容,让我们来处理"static"位:
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());