繁体   English   中英

访问摘要 static 接口成员

[英]Access abstract static interface member

如何从接口IFoo或实例 object 从FooImpl获取已实现的Name

public interface IFoo {
    static abstract string Name { get; }
}

public class FooImpl : IFoo {
    public static string Name => "Foo";
}

我似乎无法从这些方法中获取Name值。 我错过了什么吗? 请注意,我想在不知道正在使用的实现的情况下从IFoo的任何实现访问Name 因此, FooImpl.Name将编译并运行,但这不是我想要直接执行的操作。

IFoo anImpl = new FooImpl();
Console.WriteLine(anImpl.Name); // [CS0176] Member 'IFoo.Name' cannot be accessed with an instance reference; qualify it with a type name instead

// I know this won't work
Console.WriteLine(IFoo.Name); // [CS8926] A static virtual or abstract interface member can be accessed only on a type parameter.

static string GetName<T>() where T : IFoo
{
    return T.Name;
}
// I know this won't work
Console.WriteLine(GetName<IFoo>()); // [CS8920] The interface 'IFoo' cannot be used as type argument. Static member 'IFoo.Name.get' does not have a most specific implementation in the interface.

static string GetName2<T>(T implementation) where T : IFoo
{
    return T.Name;
}
Console.WriteLine(GetName2(anImpl)); // [CS8920] The interface 'IFoo' cannot be used as type argument. Static member 'IFoo.Name.get' does not have a most specific implementation in the interface.

我不确定还能尝试什么。 这篇文章是相关的,但除了反思之外我没有看到答案。

请注意,我想在不知道正在使用的实现的情况下从IFoo的任何实现访问Name

是的,这是不可能的(除了反思)。 Static 抽象接口成员与任何其他 static 成员一样属于类型,而不属于实例,因此只能通过类型检索它们。 您可以使用链接答案中的解决方案或“动态”调用GetName ,即:

var fooName = typeof(...).GetMethod(nameof(....GetName))
    .MakeGenericMethod(anImpl.GetType())
    .Invoke(null, null);

您还可以将任何一种方法包装在一些帮助器中,并将处理后的类型值存储到Dictionary<Type, string> (或ConcurrentDictionary )中以减轻反射成本。 甚至预先构建字典(取决于用例)。

还有另一种方法,但它需要对类型层次结构进行一些更改。 您可以使用奇怪的重复模板模式(CRTP) + 额外方法 + 带有默认方法实现的额外通用接口:

public interface IFoo {
    static abstract string Name { get; }
    public string GetName();
}

public interface IFoo<T> : IFoo where T : IFoo<T> // CRTP
{
    string IFoo.GetName() => T.Name;
}

public class FooImpl : IFoo<FooImpl> {
    public static string Name => "Foo";
}

和用法:

IFoo anImpl = new FooImpl();
Console.WriteLine(anImpl.GetName());

您使用只读属性实现它并为其分配默认值。

public interface IFoo {
    static abstract string Name { get; }
}

public class FooImpl : IFoo {
    public static string Name {get; } = "Foo";
}

然后你读取消费的价值

public void DoStuff<T>() where T : IFoo
{
    string name = T.Name;
}

或具体实现

public void DoStuff() 
{
    string name = FooImpl.Name;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM