How can I get the current Type in a static method that is defined in an abstract class?
Please note that as the method is defined in an abstract class, I can’t use typeof.
Why would I want to do this? A possible usage is attributes. Consider the following example:
[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);
EDIT:
Here is the scenario.
Entity represents a 3D object. I’m writing a server software, that has a list of such entities. The server manually serializes the list and sends it to the client. As performance is highly important here, I’m not sending the type name. Every type of entity has a unique identifier, so when the client gets the data, it can efficiently deserialize it.
To create an instance of an entity, I’m doing something like:
Entity entity = EntityRepository.Instance.CreateNew(identifier);
The EntityRepository class looks like this:
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();
}));
}
}
The current Add<T> method has a parameter that represents the identifier.
But how would I write a Add<T> method that has no parameters – that recognizes the identifier automatically?
So I was thinking about adding an attribute to the nested Entity:
[Identifier(1000)]
public class Rock : Entity { }
and a static property that returns the value of the Identifier attribute.
Then, an Add<T> method without parameters would look something like:
public void Add<T>(ushort id)
where T : Entity, new()
{
_repo.Add(T.Identifier, new Func<Entity>(() =>
{
return new T();
}));
}
Note that in this case, I could just do T.GetType() to get the attribute, but that’s not the point. How can I do that in the static property, Entity.Identifier?
You can’t, basically.
A call to
Rock.Identifierwill be resolved by the compiler toEntity.Identifier– there simply isn’t any context in which to find the type.A call to
rock.Identifierwon’t even compile, as you’re trying to access a static member through a variable.The best workaround would depend on the real scenario – in the case you’ve posted, I’d suggest creating a static method elsewhere which accepted a type as a parameter.
Actually, you could fake it in a really horrible way for your specific scenario by using the compile-time type of
Rock:Then:
But this would not be polymorphic. For example:
You could change the extension method to call
GetType()of course…