Reputation: 27945
ASP.NET MVC4 razor helper cannot pass type parameters to generic methods. To fix this, probably best way is to add non-generic get method with signature
public static string Get(Type entityType)
How to add this wrapper so it calls generic Get method in this class. Should reflection used or is there better way?
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class LocalizableDisplayNameAttributeI : DisplayNameAttribute
{
public LocalizableDisplayNameAttributeI(string displayName) : base(displayName) { }
public override string DisplayName
{
get
{
return global::Res.Translate(base.DisplayName);
}
}
public static string Get<TEntity>()
{
foreach (LocalizableDisplayNameAttributeI attrib in
typeof(TEntity).GetCustomAttributes(typeof(LocalizableDisplayNameAttributeI), true))
{
return attrib.DisplayName;
}
return typeof(TEntity).Name;
}}
Upvotes: 0
Views: 299
Reputation: 13224
You can do that using reflection as @JeppeStigNielsen already indicated.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class LocalizableDisplayNameAttributeI : DisplayNameAttribute
{
private static readonly MethodInfo _getMethod = typeof(LocalizableDisplayNameAttributeI)
.GetMethods().First(x => x.IsGenericMethod && x.Name == "Get");
public LocalizableDisplayNameAttributeI(string displayName) : base(displayName) { }
public override string DisplayName
{
get
{
return global::Res.Translate(base.DisplayName);
}
}
public static string Get(Type entityType)
{
return (string)_getMethod.MakeGenericMethod(entityType).Invoke(null, null);
}
public static string Get<TEntity>()
{
var attrib = typeof(TEntity)
.GetCustomAttributes(typeof(LocalizableDisplayNameAttributeI), true)
.FirstOrDefault() as LocalizableDisplayNameAttributeI;
return attrib != null ? attrib.DisplayName : typeof(TEntity).Name;
}
}
But it seems you don't really need this, because you are not using the template argument.
You can simply do:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class LocalizableDisplayNameAttributeI : DisplayNameAttribute
{
public LocalizableDisplayNameAttributeI(string displayName) : base(displayName) { }
public override string DisplayName
{
get
{
return global::Res.Translate(base.DisplayName);
}
}
public static string Get(Type entityType)
{
var attrib = entityType
.GetCustomAttributes(typeof(LocalizableDisplayNameAttributeI), true)
.FirstOrDefault() as LocalizableDisplayNameAttributeI;
return attrib != null ? attrib.DisplayName : entityType.Name;
}
public static string Get<TEntity>()
{
return Get(typeof(TEntity));
}
}
Upvotes: 1
Reputation: 6813
Going from a Type
to a generic call is a pain, but going from a generic call to a Type
is easy. Can you swap your wrapper order?
public static string Get<TEntity>()
{
return Get(typeof(TEntity));
}
public static string Get(Type entityType)
{
foreach (LocalizableDisplayNameAttributeI attrib in
entityType.GetCustomAttributes(typeof(LocalizableDisplayNameAttributeI), true))
{
return attrib.DisplayName;
}
return entityType.Name;
}
Upvotes: 1
Reputation: 61972
Reflection.
return (string)(
typeof(LocalizableDisplayNameAttributeI)
.GetMethod("Get")
.MakeGenericMethod(entityType)
.Invoke(null, null)
);
This answer only relates to how to call a generic method. However in the actual case, it is much easier to just write the method again in a non-generic version. Because you only use TEntity
in the context typeof(TEntity)
. Therefore you could simply search-and-replace typeof(TEntity)
by entityType
to get your non-generic version of the method.
Upvotes: 1