Метод расширения С# для проверки атрибутов
Извините, если это глупый вопрос о нобе, будьте осторожны со мной, я пытаюсь научиться...
Я хочу протестировать методы атрибутов таких вещей, как модели и контроллеры. В основном, чтобы удостовериться, что у них есть правильное attrbute, т.е. Обязательно. Но я также использую это как эксперимент с методами расширения и Lambdas.
То, что я хотел бы, это метод, который при имплантировании выглядит примерно так:
Controller controller = new Controller();
controller.MethodName(params).HasAttribute<AttributeName>();
Iveused методы расширения немного, но не в этой степени. Я уверен, что это должно быть достаточно простым, но не может показаться, что мои дженерики и т.д. правильны.
Ответы
Ответ 1
Возможно, вы ищите это:
Controller controller = new Controller();
bool ok = controller.GetMethod(c => c.MethodName(null, null))
.HasAttribute<AttributeName>();
Что приятно писать так, так это то, что вы полностью компилируете поддержку времени. Все остальные решения до сих пор используют строковые литералы для определения методов.
Ниже приведены реализации методов расширения GetMethod
и HasAttribute<T>
:
public static MethodInfo GetMethod<T>(this T instance,
Expression<Func<T, object>> methodSelector)
{
// Note: this is a bit simplistic implementation. It will
// not work for all expressions.
return ((MethodCallExpression)methodSelector.Body).Method;
}
public static MethodInfo GetMethod<T>(this T instance,
Expression<Action<T>> methodSelector)
{
return ((MethodCallExpression)methodSelector.Body).Method;
}
public static bool HasAttribute<TAttribute>(
this MemberInfo member)
where TAttribute : Attribute
{
return GetAttributes<TAttribute>(member).Length > 0;
}
public static TAttribute[] GetAttributes<TAttribute>(
this MemberInfo member)
where TAttribute : Attribute
{
var attributes =
member.GetCustomAttributes(typeof(TAttribute), true);
return (TAttribute[])attributes;
}
Ответ 2
Я не думаю, что вы сможете реализовать это точно так, как вы описали. Часть MethodName(params)
вашего оператора фактически выполнит метод, возвращая все возвращаемые методы, а не информацию о методе.
То, что вы хотите сделать, это передать в MethodInfo
в ваш класс расширения, используя отражение. Поэтому вместо вашего примера вы, вероятно, получите что-то вроде:
controller.GetType().GetMethod(methodName).HasAttribute<AttributeName>();
Возможно, вы упростите это до одного метода расширения в классе контроллера, инкапсулируя GetType().GetMethod()
, например:
controller.MethodHasAttribute(methodName, attributeName);
Ответ 3
Невозможно выполнить именно это с помощью методов расширения, но это близко:
public static class Program
{
static void Main(string[] args)
{
Controller c1 = new Controller();
Action a1 = c1.Method1;
Console.WriteLine(a1.HasAttribute<Controller.TestAttribute>());
}
public static bool HasAttribute<T>(this Action method)
{
return method.Method.GetCustomAttributes(typeof(T), false).Any();
}
}
class Controller
{
[AttributeUsage(AttributeTargets.Method)]
public class TestAttribute : System.Attribute
{
}
[Test()]
public void Method1()
{
}
}
Ответ 4
Применение:
bool hasAttribute = controller.HasMethodAttribute<TestAttribute>( "Test" )
Расширение:
public static bool HasMethodAttribute<TAttribute>( this object obj, string methodName )
{
Type type = obj.GetType();
MethodInfo method = type.GetMethod( methodName );
if( method == null )
{
throw new ArgumentException( string.Format(
"Method '{0}' not found on object '{1}'", methodName, type.Name ) );
}
return method.GetCustomAttributes( typeof( TAttribute ), true ).Length > 0 ;
}
Ответ 5
Вы можете проверить, имеет ли метод определенный атрибут, выполнив следующее:
typeof(Controller).GetMethod("MethodName").GetAttributes<AttributeName>().Any();
В терминах самого метода расширения при условии, что вы ищете метод расширения для типа контроллера, как насчет чего-то вроде этого:
public static bool HasAttribute<A>(this Controller controller, string methodName)
{
return controller.GetType().GetMethod(methodName).GetCustomAttributes(typeof(A), true).Any();
}
Помните, что в экземпляре вызывается метод расширения, поэтому для его использования вам все равно нужен экземпляр Controller:
var controller = new Controller();
Assert.IsTrue(controller.HasAttribute<AttributeName>("Method1"));
Ответ 6
Вы ищете Reflection class - он позволяет вам просматривать переданный объект.
Но, откровенно говоря, кроме обучения, это то, для чего существуют интерфейсы, если вы хотите, чтобы там было поле "Обязательный" в модели или метод "IsRequired" в контроллере, чем реализованный в интерфейсе, и потребовали, чтобы этот интерфейс был реализован.
В частности, для атрибутов см. здесь:
Type t = something;
System.Console.WriteLine("Author information for {0}", t);
System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t); // reflection
foreach (System.Attribute attr in attrs)
{
if (attr is Author)
{
Author a = (Author)attr;
System.Console.WriteLine(" {0}, version {1:f}", a.GetName(), a.version);
}
}