Извините, если это - глупый вопрос о новичке быть нежным со мной, я пытаюсь учиться...
Я хочу протестировать против методов атрибута вещей как модели и контроллеры. Главным образом для проверки они имеют право attrbute т.е. Необходимый. Но я также использую это в качестве эксперимента с дополнительными методами и Лямбдами.
То, что я хотел бы, является методом что когда реализованные взгляды некоторая вещь как
Controller controller = new Controller();
controller.MethodName(params).HasAttribute<AttributeName>();
Методы расширения Iveused немного, но не до этого градуса.. Я уверен, что это должно быть достаточно просто сделать, но наклониться, кажется, добираются, мои дженерики и т.д. исправляют.
Возможно, вы ищете это:
Controller controller = new Controller();
bool ok = controller.GetMethod(c => c.MethodName(null, null))
.HasAttribute<AttributeName>();
Что хорошего в том, чтобы писать так, как это что у вас есть полная поддержка времени компиляции. Все остальные решения до сих пор используют строковые литералы для определения методов.
Вот реализации методов расширения GetMethod
и HasAttribute
:
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;
}
Вы ищете класс Reflection - он позволяет вам исследовать переданный объект.
Но, честно говоря, помимо обучающего упражнения, интерфейсы существуют для этого, если вы хотите, чтобы в модели было поле с именем Required или метод с именем 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);
}
}
Я не думаю, что вы сможете реализовать это в точности так, как вы описали. Часть MethodName (params)
вашего оператора фактически выполнит метод, возвращая все, что возвращает метод, а не информацию о методе.
Что вы хотите сделать, так это передать MethodInfo
в ваш класс расширения, используя отражение. Поэтому вместо вашего примера вы, вероятно, получите что-то вроде:
controller.GetType().GetMethod(methodName).HasAttribute<AttributeName>();
Вероятно, вы могли бы упростить это до одного метода расширения в классе контроллера, инкапсулируя GetType (). GetMethod ()
, примерно так:
controller.MethodHasAttribute(methodName, attributeName);
Вы можете проверить, имеет ли метод определенный атрибут, сделав следующее:
typeof(Controller).GetMethod("MethodName").GetAttributes<AttributeName>().Any();
Что касается самого метода расширения, при условии, что вы ищете метод расширения для типа Controller, как насчет чего-то вроде этого:
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"));
Использование:
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 ;
}
Не могу точно сделать это с помощью методов расширения, но это близко:
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()
{
}
}