如何从抽象类中的静态方法获取当前类型?

Alo*_*kin 7 c# static attributes types

如何Type在抽象类中定义的静态方法中获取当前值?

请注意,由于方法是在抽象类中定义的,我无法使用typeof.

我为什么要这样做?可能的用法是属性.请考虑以下示例:

[Identifier(1000)]
public class Rock : Entity { }

public abstract class Entity
{
    public static ushort Identifier
    {
        get
        {
            // How do I get here the current type of the object?
            Type currentType = ...;

            // in a non-static method or property, I'd do:
            // Type currentType = this.GetType();

            foreach (IdentifierAttribute attribute in currentType.GetCustomAttributes(true))
                return attribute.Identifier;

            throw new EntityException("No identifier has specified for this type of entity.");
        }
    }
}

Rock rock = new Rock();

// should print 1000
Console.WriteLine(rock.Identifier);
Run Code Online (Sandbox Code Playgroud)

编辑:

这是场景.

实体表示3D对象.我正在写一个服务器软件,它有一个这样的实体列表.服务器手动序列化列表并将其发送到客户端.由于性能在这里非常重要,我不会发送类型名称.每种类型的实体都有唯一的标识符,因此当客户端获取数据时,它可以有效地反序列化它.

要创建实体的实例,我正在执行以下操作:

Entity entity = EntityRepository.Instance.CreateNew(identifier);
Run Code Online (Sandbox Code Playgroud)

这个EntityRepository类看起来像这样:

public sealed class EntityRepository
{
    private static readonly Lazy<EntityRepository> lazy =
        new Lazy<EntityRepository>(() => new EntityRepository());

    IDictionary<ushort, Func<Entity>> _repo;

    private EntityRepository()
    {
        _repo = new Dictionary<ushort, Func<Entity>>();
    }

    public static EntityRepository Instance 
    { 
        get { return lazy.Value; } 
    }

    public Entity CreateNew(ushort id)
    {
        return _repo[id]();
    }

    public void Add<T>(ushort id)
        where T : Entity, new()
    {
        _repo.Add(id, new Func<Entity>(() =>
        {
            return new T();
        }));
    }
}
Run Code Online (Sandbox Code Playgroud)

当前Add<T>方法具有表示标识符的参数.

但是,我如何编写一个Add<T>没有参数的方法 - 自动识别标识符?

所以我在考虑为嵌套添加一个属性Entity:

[Identifier(1000)]
public class Rock : Entity { }
Run Code Online (Sandbox Code Playgroud)

和一个返回Identifier属性值的静态属性.

然后,Add<T>没有参数的方法看起来像:

public void Add<T>(ushort id)
    where T : Entity, new()
{
    _repo.Add(T.Identifier, new Func<Entity>(() =>
    {
        return new T();
    }));
}
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下,我可以做到T.GetType()获取属性,但这不是重点.我怎么能在静态属性中做到这一点,Entity.Identifier

Jon*_*eet 10

基本上你不能.

调用Rock.Identifier将解决一个调用Entity.Identifier- 没有任何上下文可以找到该类型.

调用rock.Identifier甚至不会编译,因为您尝试通过变量访问静态成员.

最好的解决方法取决于实际情况 - 在你发布的情况下,我建议在其他地方创建一个静态方法,它接受一个类型作为参数.

实际上,您可以使用以下编译时类型为您的特定场景以非常可怕的方式伪造它Rock:

public static class NastyExtensions
{
    public static ushort GetIdentifier<T>(this T actualValueIsIgnored)
    {
        Type type = typeof(T);
        ... code as before
    }
}
Run Code Online (Sandbox Code Playgroud)

然后:

Rock rock = new Rock();
Console.WriteLine(rock.GetIdentifier());
Run Code Online (Sandbox Code Playgroud)

但这不是多态的.例如:

Entity rock = new Rock();
Console.WriteLine(rock.GetIdentifier()); // Bang! T would be Entity here
Run Code Online (Sandbox Code Playgroud)

您可以将扩展方法更改GetType()为当然要调用...


Ani*_*Ani 7

静态方法在C#中不是多态的 - 子类无法覆盖此实现.

编辑:基本上,正如Jon Skeet指出的那样,C#编译器会将一个调用SubType.StaticMember视为等同于BaseType.StaticMember(除非子类型提供一个具有相同名称的隐藏成员).因此,此代码将始终在该Identifier类型的"上下文"中运行,并且无法改进:

Type currentType = typeof(Identifier);
Run Code Online (Sandbox Code Playgroud)

就个人而言,我不喜欢C#甚至允许您通过'子类型访问静态成员 - 它只是设置了令人讨厌的错误和误解.