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